需求:
对每个sql进行权限控制,判断用户是查询出来的数据
由于涉及到几十个sql的改造,都要增加这个条件,一个个改很麻烦,所以通过增加sql拦截器,给每个sql追加权限条件
以flowMapper.queryOverFlowPage为例:
DynamicSqlInterceptor
实现mybatis-plus提供的InnerInterceptor ,满足条件的sql进行重写拦截
@Slf4j
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, Connection.class, Object.class})
})
public class DynamicSqlInterceptor implements InnerInterceptor {
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
String originalSql = boundSql.getSql();
if (shouldModifySql(ms)) {
String modifiedSql = modifySql(originalSql);
setSql(boundSql, modifiedSql);
}
}
……
private boolean shouldModifySql(MappedStatement statement) {
// 根据业务逻辑判断是否需要修改SQL
return statement.getId().equals("com.ht.xxx.process.dao.FlowMapper.queryOverFlowPage"); //
}
modifySql
将查询语句作为一张临时表然后拼接特定条件
@SneakyThrows
private String modifySql(String originalSql) {
// 动态修改SQL,这里加入LEFT JOIN操作
ExecutorService executorService = Executors.newFixedThreadPool(10);
SysUserDetails sysUserDetails = (SysUserDetails) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
Future<InnerData> submit = executorService.submit(new QueryTask(sysUserDetails));
InnerData innerData = submit.get();
if (innerData.getCount() > 1) {
return originalSql;
}
if (innerData.getCountBranchOrg() > 1) {
if (CollectionUtils.isNotEmpty(innerData.getAllSubDeptIds())) {
return String.format("select t.* from (%s) as t left join PrjUndertakeDept pud on t.prjId=pud.prjId where pud.deptId in (%s)", originalSql, String.join(",", innerData.getAllSubDeptIds()));
} else {
return String.format("select t.* from (%s) as t left join PrjUndertakeDept pud on t.prjId=pud.prjId where pud.deptId in (%s)", originalSql, "占位");
}
} else {
return String.format("select t.* from (%s) as t left join PrjUndertakeDept pud on t.prjId=pud.prjId where t.prjId in (%s)", originalSql, "select prjId from PrjPersonPlanPublish where userId ='" + innerData.getUserVo().getUserId() + "'");
}
}
注入
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new DynamicSqlInterceptor());
return interceptor;
}
pagehelper!
modifySql 中采用了 ExecutorService executorService = Executors.newFixedThreadPool(10); 异步,原因是因为pagehelper是根据本地线程来解决的紧跟着sql进行分页,因为拦截器里,有其他条件查询,所以pagehelper把拦截器中的查询条件作为了分页,从而导致sql日志打印正常,但是返回值错误,这里开启新的线程从而避免了污染本地线程数据!