Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

用基于接口的可扩展枚举提供更多权限支持 #286

Open
jerrylususu opened this issue Aug 1, 2021 · 1 comment
Open

用基于接口的可扩展枚举提供更多权限支持 #286

jerrylususu opened this issue Aug 1, 2021 · 1 comment
Labels
Access 权限 Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) Enhancement 增强 增强功能、提高性能等

Comments

@jerrylususu
Copy link
Contributor

APIJSON 本身的权限定义在枚举 RequestRole 中,且与框架本身的耦合度较高,如果想要在此基础上定义新的权限级别不是很方便。虽然可以通过重载 AbstractVerifier.verifyAccess 方法来自定义鉴权,但是用起来还是相对比较复杂,如(这个 issue https://github.com/Tencent/APIJSON/issues/228)。

为了尝试解决这一问题,我定义了一个新的接口 IRequestRole,令 RequestRole 实现这个接口,再依次修改框架中其他相关联的位置。通过 IRequestRole.register 方法,用户可以注册自己的权限枚举。通过 IRequestRole.get 方法,可以从权限字符串转换回对应的权限枚举。

根据我在自己的示例项目上的测试,基本可以满足需要。但是因为包含一些破坏性变更(MethodAccess 注解返回 String[]),我希望先了解下各位的意见和建议。

可以从这里获取修改后的代码(含 APIJSON ORM 和 Framework)及示例项目:
https://github.com/jerrylususu/apijson_role_extend

具体的使用方法如下:

  1. 首先定义自己的权限枚举类(可参照 apijson.demo.config.MyRole

    public enum MyRole implements IRequestRole {
        STUDENT,
        TEACHER,
        PRINCIPAL;
    }
  2. DemoApplication 的 static 块中注册自己的权限枚举类

    static {
        IRequestRole.register(MyRole.class);
        APIJSONApplication.DEFAULT_APIJSON_CREATOR = // ...
    }
  3. 在自己的用户类(model.User)中添加 List<String> role 属性,并添加对应的 getter, setter 方法

  4. 重载 AbstractVerifier.verifyAccess,补全一部分框架中未完成的鉴权逻辑(判断用户请求中声明的权限,是否的确存在于用户的权限列表中)

    此部分与用户自己的用户类的类名相关,因此没有在框架中实现(可能可以用 Visitor 接口实现?)

    // 自定义的权限,需要检查是否存在于列表中
    if ( !(config.getRole() instanceof RequestRole) ) {
        List<String> visitorRoleList = new ArrayList<>();
        // 处理数据库中 role 列为 NULL
        if (((User) this.visitor).getRole() != null) {
            visitorRoleList = ((User) this.visitor).getRole();
        }
    
        if (!visitorRoleList.contains(config.getRole().toString())){
            // 用户声明的权限不在自己的 role 列表中(伪造权限)
            throw new IllegalAccessException("当前用户没有声明的权限!");
        }
    
    }
  5. 在数据库 Access 表中完成对应配置

  • GET/GETS/HEAD/HEADS:["STUDENT", "TEACHER","PRINCIPAL"]
  • POST/DELETE:["TEACHER"]
  • PUT:["OWNER","PRINCIPAL"]
  1. 在调用时先登录,然后用 @role 声明对应的权限

    // POST /get
    {
        "[]": {
            "Course": {
                "@role": "TEACHER"
            }
        }
    }
@TommyLemon
Copy link
Collaborator

TommyLemon commented Aug 1, 2021

是一种可行方式,感谢分享,赞!

不过我倾向于把 RequestRole 改为 String,支持用户自己在 AbstractVerifier.java 的 ROLE_LIST 中添加额外的角色名,类似 AbstractSQLConfig.DATABASE_LIST 的处理,这样不管是使用还是实现都会简单很多
https://github.com/Tencent/APIJSON/blob/c663fb21e598873e3395c66192bcfadb04babf60/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java

public static String ROLE_UNKNOWN = "UNKNOWN";
public static String ROLE_OWNER = "OWNER";
...
public static List<String> ROLE_LIST = new ArrayList<>();
static {
     ROLE_LIST.add(ROLE_UNKNOWN);
     ROLE_LIST.add(ROLE_OWNER);
     ...
}

你的方案也会作为一种备选方式推荐给需要的用户~

@TommyLemon TommyLemon added Access 权限 Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) Enhancement 增强 增强功能、提高性能等 labels Aug 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Access 权限 Ecosystem 周边生态 完善生态(Go语言版、更多Demo、周边工具等) Enhancement 增强 增强功能、提高性能等
Projects
None yet
Development

No branches or pull requests

2 participants