- 如果在这里获得过启发和思考,希望点赞支持!对于内容有不同的看法欢迎来信交流。
- 技术栈 >> java
- 邮箱 >> 15673219519@163.com
- 后台系统中除了根据角色分配不同的菜单,还经常遇到在一菜单中,不同角色或者不同的人员拥有不同的查选权限。
- 查询权限又可以分为行查询,列查询。行查询实现起来比较简单,下面会简单列出我遇到到的方法;然而列权限似乎没有看到一个很好的实现方法,并且实现起来比较复杂,导致无从下手。
- 接下来,我将具体描述我在系统中的实现方式。包括对行权限,列权限。
- 行权限
- 1 通常可以通过过滤器,或者AOP等过滤掉角色或者用户没有权限查询的数据。(推荐)
- 2 也可以在搜索添加中限制只能填写有权限的搜索条件。(不推荐,该方式是可以进行绕过的)
- 列权限,操作权限
- 1 对于角色权限种类多的情况,我们可以通过在数据库记录每个角色在每个页面拥有的列,以及可以操作的功能实现列权限功能。 (推荐)
- 2 当需要区分的角色权限种类不多时,可以为不同角色编写不同的页面。这种方式仅仅适合角色不多的情况,否则开发维护成本太大。(不推荐)
- 实现目标: 涉及到的相关需要行权限的查询只要添加自定义注解@SearchPermissions就可以过滤掉没有权限的数据。如下:
@SearchPermissions
@PostMapping("/get/page")
public MSG> getListForPage(@RequestBody UserSearchDto searchDto){
// TODO
return MSG.SUCCESS();
}
- 创建自定义注解
SearchPermissions.java
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface SearchPermissions {
}
SearchPermissionsAspect.java
@Slf4j
@Aspect
@Component
public class SearchPermissionsAspect {
@Pointcut("@annotation(com.qykj.admin.aspect.SearchPermissions)")
public void pointcut() {}
@Before("pointcut()")
public void process(JoinPoint point){
// 1,TODO 通过请求获取当前请求的用户角色,查询到其有哪些查询权限
// 2,TODO 通过point获取用户查询的条件,一般会将相关的涉及到权限控制的查询字段封装公共的基类,便于在此处操作
// 3,过滤掉,该用户没有的查询条件,即可
}
}
}
列权限(提供实现的思路,具体部分细节需要根据不同项目实际情况)
- 实现目标: 涉及到的相关需要列权限,操作权限的查询只要添加自定义注解@FieldFilter(javaType = User.class, name = "user_list@view")就可以过滤掉没有权限的数据。如下:
@SearchPermissions
@FieldFilter(javaType = UserParent.class, name="name = "user_list@view")
@PostMapping("/get/page")
public MSG> getListForPage(@RequestBody UserSearchDto searchDto){
// TODO
return MSG.SUCCESS(listForPage);
}
- 创建自定义注解
FieldFilter.java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@documented
public @interface FieldFilter {
// 需要过滤的类 User.class过滤掉的是User类中的字段
Class javaType() default Object.class;
// 此处用于标识该请求是控制那也页面的列权限还是操作权限 (user_list@view 用户列表列权限),(user_list@opt 用户列表操作权限)
String name() default "";
}
@Aspect
@Component
public class FieldFilterAspect {
@Pointcut("@annotation(com.qykj.admin.aspect.FieldFilter)")
public void fieldFilterAspect(){}
@Around("fieldFilterAspect()")
public MSG around(JoinPoint point) throws Throwable {
// 1,TODO 通过请求获取当前请求的用户角色ID
// 2,TODO 通过point获取controller方法 @FieldFilter(javaType = User.class, name = "user_list@view"),即可知道那个页面的操作
// 3,TODO 通过 user_list@view + 角色ID 即可从数据库中获取可以返回那些字段那些操作权限
// 4,TODO 通过JSON序列化时,只序列化有权限的字段即可
return MSG;
}
}
总结
- user_list@view中user_list对应页面菜单view标识是查询列。这些完全可以自定义,主要实现TODO中的思路步骤即可实现。
- 列权限在本例中主要利用的JSON序列化,动态只序列化有权限的字段实现。还需要前端配合,根据你返回的字段渲染表单。为了确保查询为空的时候前端能够正确渲染表头,后端需要提供根据菜单标识查询有哪些字段的接口。



