从零开始,手打一个权限管理系统(第十章数据权限)
前言
这章主要讲解如何实现对表数据权限的控制,让授权用户只能看到指定范围的数据。一、实现思路
我们用组织机构ID(orgid)来作为数据权限的过滤字段,通过对sql语句添加where条件来实现对数据的过滤;这里我们需要用到MyBatisPlus的一个数据权限的插件DataPermissionInterceptor,通过实现自定义的数据权限处理器DataPermissionHandler,就可以满足我们在sql语句里面添加过滤条件的需求。二、主要代码
1、自定义数据拦截器,实现DataPermissionHandler接口packagecom。ailot。cloud。base。data。datascope;importcn。hutool。core。collection。CollUtil;importcn。hutool。db。Db;importcn。hutool。db。Entity;importcom。ailot。cloud。base。common。constants。CommonConstant;importcom。ailot。cloud。base。common。exception。CheckedException;importcom。ailot。cloud。base。data。enums。DataScopeTypeEnum;importcom。ailot。cloud。base。security。constant。SecurityConstants;importcom。ailot。cloud。base。security。model。JwtUser;importcom。ailot。cloud。base。security。utils。SecurityUtils;importcom。baomidou。mybatisplus。core。toolkit。ObjectUtils;importcom。baomidou。mybatisplus。extension。plugins。handler。DataPermissionHandler;importlombok。SneakyThrows;importnet。sf。jsqlparser。expression。Expression;importnet。sf。jsqlparser。expression。StringValue;importnet。sf。jsqlparser。expression。operators。conditional。AndExpression;importnet。sf。jsqlparser。expression。operators。relational。ExpressionList;importnet。sf。jsqlparser。expression。operators。relational。InExpression;importnet。sf。jsqlparser。expression。operators。relational。ItemsList;importnet。sf。jsqlparser。schema。Column;importorg。springframework。security。core。GrantedAuthority;importjavax。sql。DataSource;importjava。util。ArrayList;importjava。util。Arrays;importjava。util。Comparator;importjava。util。List;importjava。util。stream。Collectors;publicclassDataScopeHandlerimplementsDataPermissionHandler{privatefinalDataScopePropertiesdataScopeProperties;privatefinalDataSourcedataSource;publicDataScopeHandler(DataScopePropertiesdataScopeProperties,DataSourcedataSource){this。dataScopePropertiesdataScopeProperties;this。dataSourcedataSource;}SneakyThrowsOverridepublicExpressiongetSqlSegment(Expressionwhere,StringmappedStatementId){查询需要配置数据权限的方法ListStringmapperIdsdataScopeProperties。getMapperIds();if(CollUtil。isEmpty(mapperIds)){returnwhere;}else{if(!CollUtil。contains(mapperIds,mappedStatementId)){returnwhere;}}ListStringorgIdsnewArrayList();JwtUseruserSecurityUtils。getUser();if(usernull){thrownewCheckedException(用户信息为空);}获取角色ID列表ListStringroleIdListuser。getAuthorities()。stream()。map(GrantedAuthority::getAuthority)。filter(authorityauthority。startsWith(SecurityConstants。ROLE))。map(authorityauthority。split()〔1〕)。collect(Collectors。toList());获取角色信息EntityqueryDb。use(dataSource)。query(SELECTFROMCommonConstant。UPMSDATABASE。sysrolewhereidIN(CollUtil。join(roleIdList,,)))。stream()。min(Comparator。comparingInt(oo。getInt(dstype)))。get();IntegerdsTypequery。getInt(dstype);查询全部if(DataScopeTypeEnum。ALL。getType()dsType){returnwhere;}自定义if(DataScopeTypeEnum。CUSTOM。getType()dsType){部门范围StringdsScopequery。getStr(dsscope);orgIds。addAll(Arrays。stream(dsScope。split(,))。map(String::toString)。collect(Collectors。toList()));}只查询本级if(DataScopeTypeEnum。OWNLEVEL。getType()dsType){orgIds。add(user。getOrgId());}ItemsListitemsListnewExpressionList(orgIds。stream()。map(StringValue::new)。collect(Collectors。toList()));InExpressioninExpressionnewInExpression(newColumn(CommonConstant。ORGSCOPE),itemsList);returnObjectUtils。isNotEmpty(where)?newAndExpression(where,inExpression):inExpression;}}
简单说一下这个代码的逻辑,首先是拿到需要数据权限拦截的方法,然后获取当前用户的角色,通过角色就可以获取到数据权限类型(dstype);这里我们定义了三种类型的数据权限(全部、自定义、本级),全部就不用加where条件,自定义就是获取到指定范围dsscope的数据,本级就是当前用户所在部门的数据,然后我们只需要将这些条件拼接起来,生成一个新的sql语句就可以了。
2、配置拦截器
要使用数据拦截器需要在Mybatis配置文件里面初始化DataPermissionInterceptordataPermissionInterceptornewDataPermissionInterceptor();dataPermissionInterceptor。setDataPermissionHandler(newDataScopeHandler(dataScopeProperties,dataSource));MybatisPlusInterceptorinterceptornewMybatisPlusInterceptor();数据权限拦截interceptor。addInnerInterceptor(dataPermissionInterceptor);
3、在yml文件里面配置需要拦截的方法base:datascope:mapperIds:com。ailot。cloud。upms。api。mapper。SysUserMapper。pageUser
至此数据权限的配置就已经全部完成了,后面只需要在有拦截需求的表加上拦截字段,在yml配置文件上添加需要拦截的方法就可以实现数据权限的过滤了。三、效果展示
当前版本tag:1。0。9
代码仓库四、体验地址
后台数据库只给了部分权限,报错属于正常!
想学的老铁给点点关注吧!!!
欢迎留言交流!!!
我是阿咕噜,一个从互联网慢慢上岸的程序员,如果喜欢我的文章,记得帮忙点个赞哟,谢谢!