mybatis拦截器实现权限管理

框架设计
基于 +JWT技术实现登录认证和访问授权 , 基于 拦截器实现数据权限的控制 。由于已有前文介绍 如有兴趣可以查看 , 在此将重点于数据权限的实现及菜单等表结构的设计 。
拦截器
介绍拦截器之前先来了解一下工作流程 。
工作流程
拦截器
提供了一种插件()的功能 , 虽然叫做插件 , 但其实这是拦截器功能 。那么拦截器拦截中的哪些内容呢?
允许你在已映射语句执行过程中的某一点进行拦截调用 。默认情况下 ,  允许使用插件来拦截的方法调用包括:
(, query, , , , , close, )
(, )
(, rs)
(, , batch, , query)
我们看到了可以拦截接口的部分方法 , 比如 , query ,  , 等方法 , 还有其他接口的一些方法等 。
总体概括为:
拦截执行器的方法
拦截参数的处理
拦截结果集的处理

mybatis拦截器实现权限管理

文章插图
拦截Sql语法构建的处理
分页插件其实就是利用拦截器实现得 , 我们这也是类似 , 通过拦截器拦截执行器得方法对将要执行的sql语句进行拦截解析成Sql表达式 , 在根据认证用户所拥有的数据权限进行拼接过滤条件达到控制的效果 。整体思路并不复杂 , 难点在于如何将用户所拥有的资源传递到拦截器中 , 拦截器如何解析Sql,以及Sql的重新组装 。下面将贴出实现的核心代码 。
核心代码实现
【mybatis拦截器实现权限管理】@Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}))@Componentpublic class DataCountInterceptor implements Interceptor {private static final ReflectorFactory defaultReflectorFactory = new DefaultReflectorFactory();private static EqualsTo NO_Match = new EqualsTo();private static EqualsTo Match = new EqualsTo();static {NO_Match.setLeftExpression(new Column("1"));NO_Match.setRightExpression(new LongValue(0));Match.setLeftExpression(new Column("1"));Match.setRightExpression(new LongValue(1));}@Overridepublic Object intercept(Invocation invocation) throws Throwable {try {Object[] args = invocation.getArgs();MappedStatement ms = (MappedStatement) args[0];Object parameter = args[1];RowBounds rowBounds = (RowBounds) args[2];ResultHandler resultHandler = (ResultHandler) args[3];Executor executor = (Executor) invocation.getTarget();CacheKey cacheKey;BoundSql boundSql;//由于逻辑关系 , 只会进入一次if (args.length == 4) {//4 个参数时boundSql = ms.getBoundSql(parameter);cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);} else {//6 个参数时cacheKey = (CacheKey) args[4];boundSql = (BoundSql) args[5];}//TODO 自己要进行的各种处理String id = ms.getId();id = id.substring(0, id.lastIndexOf('.'));MybatisDataAuthority localDataAuthority = DataPermissionHelper.getLocalDataAuthority();// 超级管理员放行if (localDataAuthority != null && localDataAuthority.getSuperAdmin() != 1) {String operatorAlias = Strings.isNotBlank(localDataAuthority.getOperatorAlias()) ? localDataAuthority.getOperatorAlias() : "operator";String gameAlias = Strings.isNotBlank(localDataAuthority.getGameAlias()) ? localDataAuthority.getGameAlias() : "game_code";String mediaAlias = Strings.isNotBlank(localDataAuthority.getMediaAlias()) ? localDataAuthority.getMediaAlias() : "media_code";String sql = boundSql.getSql();Statement sm = CCJSqlParserUtil.parse(sql);Select select = (Select) sm;assert select != null;SelectBody selectBody = select.getSelectBody();PlainSelect plainSelect = (PlainSelect) selectBody;// 设置whereExpression expression = Match;if (localDataAuthority.isHasOperator() && !localDataAuthority.isAllOperator()) {if (CollectionUtils.isEmpty(localDataAuthority.getOperators())) {expression = NO_Match;} else {List