这里写目录标题
配置文件里面加上自定义的拦截器
package com.xueyi.common.web.config;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
import com.github.pagehelper.PageInterceptor;
import com.xueyi.common.datascope.interceptor.XueYiDataScopeHandler;
import com.xueyi.common.web.handler.TenantLineHandler;
import com.xueyi.common.web.handler.XueYiMetaObjectHandler;
import com.xueyi.common.web.injector.CustomizedSqlInjector;
import com.xueyi.common.web.interceptor.CustomerInnerInterceptor;
import com.xueyi.common.web.interceptor.TenantLineInnerInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MP配置
*
* @author xueyi
*/
@Configuration
public class XueYiMyBatisPlusConfig {
@Autowired
private XueYiDataScopeHandler dataScopeAspect;
@Autowired
private TenantLineHandler tenantLineHandler;
/**
* PageHelper分页配置
*/
@Bean
public PageInterceptor pageInterceptor() {
return new PageInterceptor();
}
/**
* 方法注入
*/
@Bean
public CustomizedSqlInjector customizedSqlInjector() {
return new CustomizedSqlInjector();
}
/**
* 自动填充
*/
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new XueYiMetaObjectHandler());
return globalConfig;
}
/**
* 插件配置
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 数据权限插件
interceptor.addInnerInterceptor(new DataPermissionInterceptor(dataScopeAspect));
// 租户控制插件
interceptor.addInnerInterceptor(new TenantLineInnerInterceptor(tenantLineHandler));
// 禁全表更删插件
interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
// //客户权限的拼接
interceptor.addInnerInterceptor(new CustomerInnerInterceptor());
return interceptor;
}
}
自定义的拦截器
(这里做的功能就是发现是查询的情况,先看看表是否需要进行客户权限控制的,如果是的话,去线程里面去取授权的客户,如果没有的话就去查询,然后塞到线程变量里面去)
package com.xueyi.common.web.interceptor;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.BaseMultiTableInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.xueyi.common.cache.utils.DictUtil;
import com.xueyi.common.core.context.SecurityContextHolder;
import com.xueyi.common.core.i18n.MessageUtils;
import com.xueyi.common.core.utils.core.ObjectUtil;
import com.xueyi.common.core.web.result.R;
import com.xueyi.common.security.utils.SecurityUtils;
import com.xueyi.system.api.dict.feign.RemoteDictService;
import com.xueyi.system.api.domain.dto.UserCustomerDto;
import com.xueyi.system.api.domain.query.UserCustomerQuery;
import com.xueyi.system.api.feign.RemoteSystemUserCustomerService;
import lombok.Value;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.WithItem;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* 针对客户权限的拦截器
*
* @author chenwen
*/
@Component
public class CustomerInnerInterceptor extends BaseMultiTableInnerInterceptor implements InnerInterceptor {
@Resource
private RemoteSystemUserCustomerService remoteUserCustomerService;
private static final String CUSTOMER_ID_COLUMN = "customer_id";
//需要进行客户控制的表
private static final List<String> TABLE_LIST = List.of(
"tms_trans_order",
"tms_trans_shipment",
"bms_rece_contract"
);
/**
* 查询的拦截器
* @param executor Executor(可能是代理对象)
* @param ms MappedStatement
* @param parameter parameter
* @param rowBounds rowBounds
* @param resultHandler resultHandler
* @param boundSql boundSql
* @throws SQLException
*/
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
//首先不是客户忽略的(没有显示设置 其实都是客户不忽略的)
if (!SecurityContextHolder.getCustomerIgnore()){
//获取查询前的sql语句,用JsqlParserSupport把sql语句解析成对应的语法树
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
mpBs.sql(this.parserSingle(mpBs.sql(), (Object) null));
}
}
/**
* 如果解析到select语句
* @param select
* @param index
* @param sql
* @param obj
*/
@Override
protected void processSelect(Select select, int index, String sql, Object obj) {
String whereSegment = (String) obj;
this.processSelectBody(select.getSelectBody(), whereSegment);
List<WithItem> withItemsList = select.getWithItemsList();
if (!ObjectUtil.isEmpty(withItemsList)) {
withItemsList.forEach((withItem) -> {
this.processSelectBody(withItem, whereSegment);
});
}
}
/**
* 只对查询进行控制
* @param sh StatementHandler(可能是代理对象)
* @param connection Connection
* @param transactionTimeout transactionTimeout
*/
@Override
public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
MappedStatement ms = mpSh.mappedStatement();
SqlCommandType sct = ms.getSqlCommandType();
if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
//增删改查暂不处理
return;
}
}
/**
* 额外添加条件
* @param table 表对象
* @param where 当前where条件
* @param whereSegment 所属Mapper对象全路径
* @return
*/
@Override
public Expression buildTableExpression(Table table, Expression where, String whereSegment) {
// 检查是否需要添加 customer_id 条件
if (isTableNeedCustomerId(table)) {
List<Long> ids= SecurityContextHolder.getCustomerIdList();
//先去当前的localthread里面那里是否有值,如果为null代表是没查过
if (ids==null){
ids= selectCustomerIds();
}
//有客户的情况下才拼接(客户这边的逻辑是如果没有授权客户代表全部客户)
if (ObjectUtil.isNotEmpty(ids)){
InExpression customerIdCondition = new InExpression();
customerIdCondition.setLeftExpression(getAliasColumn(table,CUSTOMER_ID_COLUMN));
customerIdCondition.setRightExpression(getRightExpression(ids));
return customerIdCondition;
}
}
return null;
}
//判断表是否需要加上客户权限的
private boolean isTableNeedCustomerId(Table table) {
// 判断哪些表需要添加 customer_id 条件
return TABLE_LIST.contains(table.getName());
}
/**
处理条件后面拼接的值,customerid in (1,2)
*/
protected Column getRightExpression(List<Long> list) {
StringBuilder values = new StringBuilder();
values.append("(");
for (int i = 0; i < list.size(); i++) {
Long item = list.get(i);
values.append(item);
if (i< list.size()-1){
values.append(",");
}
}
values.append(")");
return new Column(values.toString());
}
// /**
// * 表别名设置
// * org_id 或 tableAlias.org_id
// * @param table 表对象
// * @return 字段
// */
protected Column getAliasColumn(Table table, String columnName) {
StringBuilder column = new StringBuilder();
if (table.getAlias() != null) {
column.append(table.getAlias().getName()).append(".").append(columnName);
}else{
column.append(table.getName()).append(".").append(columnName);
}
return new Column(column.toString());
}
private List<Long> selectCustomerIds(){
SecurityContextHolder.getCustomerIdList();
UserCustomerQuery userCustomerQuery= new UserCustomerQuery();
userCustomerQuery.setUserId(SecurityUtils.getUserId());
if (ObjectUtil.isNull(remoteUserCustomerService)){
remoteUserCustomerService= SpringUtil.getBean(RemoteSystemUserCustomerService.class);
}
R<List<UserCustomerDto>> userCustomerDtoList= remoteUserCustomerService.listInner(userCustomerQuery);
if (userCustomerDtoList.isFail()){
logger.error(MessageUtils.message("getAuthCustomerError"));
throw new RuntimeException(MessageUtils.message("getAuthCustomerError"));
}
//如果内容为空就塞空长度的集合(不要塞null)
if (ObjectUtil.isEmpty(userCustomerDtoList.getData())){
SecurityContextHolder.setCustomerIdList(Collections.emptyList());
return Collections.emptyList();
}else{
List<Long> customerIds= userCustomerDtoList.getData().stream().map(UserCustomerDto::getCustomerId).collect(Collectors.toList());
SecurityContextHolder.setCustomerIdList(customerIds);
return customerIds;
}
}
}