系统数据权限的实现方案

系统数据权限的实现方案


  目前正在开发的OA系统希望实现这样一个需求:每个使用系统的用户具有某种基于工号和组织架构的权限,主要区分为可以查看个人、查看本部门或指定部门以及查看所有。这样的权限控制称之为数据范围。

    对于数据范围的实现主要通过以下方案:

1.配置数据依赖表,数据依赖表中有以下字段:主表的空间、主表、主表别称、依赖表、依赖表别名

数据库表定义如下;

T_sys_table_dependence


wKiom1TGEzuTCrIRAAE--SpHqsk443.jpg

2.mybatis.xml配置拦截器。Mybatis所谓的拦截器的一个作用就是可以拦截某些方法的调用,可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。比如在本方案中即可根据当前用户的数据范围动态的组装成sql作为所有查询sql的附加逻辑。Mybatis拦截器需要实现其接口Interceptor,其接口如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
package  org.apache.ibatis.plugin;
 
import  java.util.Properties;
 
public  interface  Interceptor {
 
   Object intercept(Invocation invocation)  throws  Throwable;
 
   Object plugin(Object target);
 
   void  setProperties(Properties properties);
 
}

    通过该接口定义,可以看出实现一个mybatis拦截器最重要的是实现三述三个接口方法。Intercept方法定义拦截的时候需要实现的逻辑;plugin方法决定是否拦截以及返回的目标对象;而setProperties则是将拦截器配置中的参数信息映射进来。

  本方案中对该接口的实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public  Object intercept(Invocation invocation)  throws  Throwable {
     Object[] args = invocation.getArgs();
     MappedStatement ms = (MappedStatement) args[ 0 ];
     Object parameter = args[ 1 ];
     RowBounds rowBounds = (RowBounds) args[ 2 ];
     int  offset = rowBounds.getOffset();
     int  limit = rowBounds.getLimit();
     List<TabledependenceEntity> list = DataRuleConstants.CACHE_TABLEDEPENDENCEMAP.get(ms.getId());
     if (!CollectionUtils.isEmpty(list)){
         BoundSql boundSql = ms.getBoundSql(parameter);
         String sql = boundSql.getSql().trim();
         //add data rule:yourself logic
         sql = dataruleHandler.addConditionToSql(sql, list);
         BoundSql newBoundSql =  new  BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject());
         copyMetaParameters(boundSql, newBoundSql);
         MappedStatement newMs = copyFromMappedStatement(ms,  new  BoundSqlSqlSource(newBoundSql));
         args[ 0 ] = newMs;
     }
     return  invocation.proceed();
}

  另外,mybatis拦截器还有两个注解特别重要,一个是@Intercepts,其值是一个@Signature数组。@Intercepts用于表明当前的对象是一个Interceptor,而@Signature则表明要拦截的接口、方法以及对应的参数类型。本应用中配置如下:

1
2
@Intercepts ({ @Signature (type = Executor. class , method =  "query" , args = { 
     MappedStatement. class , Object. class , RowBounds. class , ResultHandler. class  }) })

  以上配置的含义是:当Executor代理对象在执行参数类型为MappedStatement、Object、RowBounds和ResultHandler的query方法时,拦截器就会进行拦截,而对其他的请求则直接返回代理对象,而非目标对象。

3.通过配置Mybatis.xml注册拦截器,配置如下:

1
2
3
< plugin  interceptor = "com.fx.oa.module.com.dependence.server.service.impl.DataRuleIntercept" >
             < property  name = "dataruleHandler"  value = "com.fx.oa.module.com.dependence.server.service.impl.DataruleHandler" />
         </ plugin >

  通过以上三个步骤,即实现了一个mybatis的拦截器。

4.下面将会对数据范围实现的逻辑进行介绍,即本文第2段落的内容  

1
//add data rule:yourself logic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
private  String filterSpecialValue(String field, String value) {
         if  ( "deptCode" .equals(field)){
             if ( "1" .equals(value)){
                 return  null ;
             }
             if (DataRuleConstants.VALUE_CURRENTDEPTCODE.equals(value)){
                 value = OAUserContext.getOrgCode();
             }
             //获取当前部门的所有子部门
             orgService = (IOrgService) SpringContextUtil.getApplicationContext().getBean( "orgService" );
             String[] valus = value.split( "," );
             List<String> orgList =  new  ArrayList<String>();
             for (String val : valus){
                 if (StringUtils.isNotEmpty(val)){
                     orgList.addAll(orgService.queryOrgChildCode(val));
                 }
             }
             if (!CollectionUtils.isEmpty(orgList)){
                 for (String org : orgList){
                 value +=  ","  + org;
                 }
             }
         } else  if ( "userCode" .equals(field)){
             if (DataRuleConstants.VALUE_CURRENTUSERCODE.equals(value)){
                 value = OAUserContext.getUserCode();
             }
         }
         return  value;
     }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public  String addConditionToSql(String sql, List<TabledependenceEntity> list) {
         TabledependenceEntity td = list.get( 0 );
         String mybatisId = td.getMybatisId();
         String lowerSql = sql.toLowerCase();
         StringBuffer sqlString =  new  StringBuffer();
         List<DataruleEntity> ruleList = getRelatedDatarule(sql, td);
         if (!CollectionUtils.isEmpty(ruleList)){
             String searchTable = td.getTableName();
             String whereSql = lowerSql.split(DataRuleConstants.SQL_ORDERBY)[ 0 ] +  " " ;
             String orderSql =  "" ;
             boolean  containsOrder = lowerSql.contains(DataRuleConstants.SQL_ORDERBY);
             if (containsOrder){
                 orderSql =  " "  + DataRuleConstants.SQL_ORDERBY + lowerSql.split(DataRuleConstants.SQL_ORDERBY)[ 1 ];
             }
             StringBuffer generatedSql = generateDynamicSql(lowerSql, ruleList, td);
             return  (sqlString.append(whereSql).append(generatedSql).append(orderSql)).toString();
         } else  {
             return  sql;
         }
     }

    通过mybatis拦截器为所有查询请求添加并执行额外逻辑,较优雅地实现了DAO底层次的统一处理的封装问题,很好地解决了系统对数据权限的要求。  

更多关于拦截器方面的知识,可以参考以下文章:


Mybatis拦截器介绍及分页插件


MYBATIS 配置文件(转载)




     本文转自 gaochaojs 51CTO博客,原文链接:http://blog.51cto.com/jncumter/1608556,如需转载请自行联系原作者


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JeeSpringCloud是一个基于SpringBoot2.0的后台权限管理系统,界面简洁美观敏捷开发系统架构。核心技术采用Spring、MyBatis、Shiro没有任何其它重度依赖。 互联网云快速开发框架,微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中分布式、微服务,同时包含许多基础模块和监控、服务模块。模块包括:定时任务调度、服务器监控、平台监控、平台设置、开发平台、单点登录、Redis分布式高速缓存、会员、营销、在线用户、日志、在线人数、访问次数、调用次数、直接集群、接口文档、生成模块、代码实例、安装视频、教程文档 代码生成(单表、主附表、树表、列表和表单、redis高速缓存对接代码、图表统计、地图统计、vue.js)、dubbo、springCloud、SpringBoot、mybatis、spring、springmvc。 功能 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 岗位管理:配置系统用户所属担任职务。 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 参数管理:对系统动态配置常用参数。 通知公告:系统通知公告信息发布维护。 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 登录日志:系统登录日志记录查询包含登录异常。 在线用户:当前系统中活跃用户状态监控。 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 代码生成:前后端代码生成(单表、主附表、树表、列表和表单、增删改查云接口、redis高速缓存对接代码、图表统计、地图统计、vue.js) ,并生成菜单和权限直接使用。 系统接口:根据业务代码自动生成相关的api接口文档。 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 在线接口文档:使用swager生成在线文档。 ActiveMQ队列:提供ActiveMQ队列,处理批量发送大数据量邮件、大数据量日志文件。 工作流:功能包括在线办公、我的任务、审批测试、流程管理、模型管理。 CMS:功能包括内容管理、内容管理、统计分析、栏目设置、首页。 dubbo:代码生成直接生成dubbo对接代码。 服务器Down机邮件监控:通过定时任务监控服务器是否Down机,并发送通知邮件。 服务器监控:通过sigar进行服务器图形化监控。 异常邮件监控:全局拦截系统异常,并发送通知邮件。 单点登录:使用shior和Redis、共享session方式实现单点登录。 Redis分布式高速缓存:代码生成直接生成Redis对接代码。 特性: JeeSpringCloud基于SpringBoot+SpringMVC+Mybatis+Redis+SpringCloud+Vue.js微服务分布式代码生成的敏捷开发系统架构。项目代码简洁,注释丰富,上手容易,还同时集中分布式、微服务,同时包含许多基础模块(用户管理,角色管理,部门管理,字典管理等10个模块。成为大众认同、大众参与、成就大众、大众分享的开发平台。JeeSpring官方qq群(328910546)。代码生成前端界面、底层代码(spring mvc、mybatis、Spring boot、Spring Cloud、微服务的生成)、安全框架、视图框架、服务端验证、任务调度、持久层框架、数据库连接池、缓存框架、日志管理、IM等核心技术。努力用心为大中小型企业打造全方位J2EE企业级平台ORM/Redis/Service仓库开发解决方案。一个RepositoryService仓库就直接实现dubbo、微服务、基础服务器对接接口和实现。 努力用心为大中小型企业打造全方位J2EE企业级平台开发解决方案。 Spring Boot/Spring cloud微服务是利用云平台开发企业应用程序的最新技术,它是小型、轻量和过程驱动的组件。微服务适合设计可扩展、易于维护的应用程序。它可以使开发更容易,还能使资源得到最佳利用。 微服务/集群(nignx) 支持REST风格远程调用(HTTP + JSON/XML):基于非常成熟的Spring Boot框架,在Spring Boot Spring Cloud中实现了REST风格(HTTP + JSON/XML)的远程调用,以显著简化企业内部的跨语言交互,同时显著简化企业对外的Open API、无线API甚至AJAX服务端等等的开发。 事实上,这个REST调用也使得Dubbo可以对当今特别流行的“微服务”架构提供基础性支持。 另外,REST调用也达到了比较高

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值