小明有权限1:
{ "code": "200", "msg": "查询成功", "data": [ { "name": "name1", "id": "1", "creater": "xiaoming" }, { "name": "name2", "id": "2", "creater": "xiaoming" } ] }
大明具有权限2,小明相同部门
{ "code": "200", "msg": "查询成功", "data": [ { "name": "name1", "id": "1", "creater": "xiaoming" }, { "name": "name2", "id": "2", "creater": "xiaoming" }, { "name": "name3", "id": "3", "creater": "daming" }, { "name": "name4", "id": "4", "creater": "daming" } ] }
领导有权限3,可以看到全部
{ "code": "200", "msg": "查询成功", "data": [ { "name": "name1", "id": "1", "creater": "xiaoming" }, { "name": "name2", "id": "2", "creater": "xiaoming" }, { "name": "name3", "id": "3", "creater": "daming" }, { "name": "name4", "id": "4", "creater": "daming" }, { "name": "name5", "id": "5", "creater": "mingming" } ] }
@Intercepts({<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E-->MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})@Slf4jpublic class MapperPermissionInterceptor implements Interceptor {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E--> @Override public Object intercept(Invocation invocation) throws Throwable {<!--{cke_protected}{C}%3C!%2D%2D%20%2D%2D%3E--> Object target = invocation.getTarget(); //被代理对象 Method method = invocation.getMethod(); //代理方法 Object[] args = invocation.getArgs(); //方法参数MappedStatement mappedStatement = (MappedStatement) args[0]; Object parameterObject = args[1]; // do something ...方法拦截前执行代码块 Object result = invocation.proceed(); // do something ...方法拦截后执行代码块 return result; } }@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) @Slf4j public class MapperPermissionInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Object target = invocation.getTarget(); //被代理对象 Method method = invocation.getMethod(); //代理方法 Object[] args = invocation.getArgs(); //方法参数 MappedStatement mappedStatement = (MappedStatement) args[0]; Object parameterObject = args[1]; // do something ...方法拦截前执行代码块 Object result = invocation.proceed(); // do something ...方法拦截后执行代码块 return result; } }
原 originalSql
select id, name, creater from tt
通过 mybatis 的切面实现
在前面添加 select * from ( ,后面添加 where 条件
select * from ( select id, name, creater from tt ) tmp where creater = "daming"
@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) @Slf4j public class MapperPermissionInterceptor implements Interceptor { @Autowired PermissionProperty permissionProperty; public static final String PACK_START_SQL = "select * from ( "; public static final String PACK_END_SQL = ") tmp "; public static final String PERMISSION_Y = "y"; @Override public Object intercept(Invocation invocation) throws Throwable { if(!PERMISSION_Y.toLowerCase().equals(permissionProperty.getMapper().toLowerCase())){ log.info("mapper 权限未开启"); return invocation.proceed(); } MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; Object parameter = invocation.getArgs()[1]; BoundSql boundSql = mappedStatement.getBoundSql(parameter); String originalSql = boundSql.getSql().trim(); String id = mappedStatement.getId(); log.info("originalSql: {} ", originalSql); log.info("id: {}", id); String name = getMapperName(id); String method = getMapperMethod(id); log.info("name: {}, method: {} ", name, method); String joinSql = dataPermissionSqlProvider().getJoinSql(name, method); log.info("joinSql: {} ", joinSql); if (Optional.ofNullable(joinSql).isPresent()) { BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, this.joinSql(originalSql, joinSql)); ParameterMap map = mappedStatement.getParameterMap(); MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql), map); invocation.getArgs()[0] = newMs; } return invocation.proceed(); } /** * 获取 Mapper 名称 * @param id * @return */ private String getMapperName(String id) { String name = id.substring(0, id.lastIndexOf(".")); return name.substring(name.lastIndexOf(".") + 1); } /** * 获取 Mapper 方法 * @param id * @return */ private String getMapperMethod(String id) { String method = id.substring(id.lastIndexOf(".") + 1); return method; } private DataPermissionProvider dataPermissionSqlProvider() { return (DataPermissionProvider) ApplicationContextUtil.getBean("dataPermissionProvider"); } private String joinSql(String sql, String selectSql) { sql = PACK_START_SQL + sql + PACK_END_SQL + selectSql; log.info("packSql: {}", sql); return sql; } public static class BoundSqlSqlSource implements SqlSource { BoundSql boundSql; public BoundSqlSqlSource(BoundSql boundSql) { this.boundSql = boundSql; } @Override public BoundSql getBoundSql(Object parameterObject) { return boundSql; } } private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) { BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject()); for (ParameterMapping mapping : boundSql.getParameterMappings()) { String prop = mapping.getProperty(); if (boundSql.hasAdditionalParameter(prop)) { newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop)); } } return newBoundSql; } /** * 复制MappedStatement对象 */ private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource, ParameterMap parameterMap) { MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType()); builder.resource(ms.getResource()); builder.fetchSize(ms.getFetchSize()); builder.statementType(ms.getStatementType()); builder.keyGenerator(ms.getKeyGenerator()); builder.timeout(ms.getTimeout()); builder.parameterMap(parameterMap); builder.resultMaps(ms.getResultMaps()); builder.resultSetType(ms.getResultSetType()); builder.cache(ms.getCache()); builder.flushCacheRequired(ms.isFlushCacheRequired()); builder.useCache(ms.isUseCache()); return builder.build(); } }