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`) ```java public enum MyRole implements IRequestRole { STUDENT, TEACHER, PRINCIPAL; } ``` 2. 在 `DemoApplication` 的 static 块中注册自己的权限枚举类 ```java static { IRequestRole.register(MyRole.class); APIJSONApplication.DEFAULT_APIJSON_CREATOR = // ... } ``` 3. 在自己的用户类(`model.User`)中添加 `List<String> role` 属性,并添加对应的 getter, setter 方法 4. 重载 `AbstractVerifier.verifyAccess`,补全一部分框架中未完成的鉴权逻辑(判断用户请求中声明的权限,是否的确存在于用户的权限列表中) > 此部分与用户自己的用户类的类名相关,因此没有在框架中实现(可能可以用 `Visitor` 接口实现?) ```java // 自定义的权限,需要检查是否存在于列表中 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"] 6. 在调用时先登录,然后用 `@role` 声明对应的权限 ```json // POST /get { "[]": { "Course": { "@role": "TEACHER" } } } ```
Activity
TommyLemon commentedon 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
你的方案也会作为一种备选方式推荐给需要的用户~