mybatisPlus自定义拦截器

该博客介绍了如何使用MybatisPlus的自定义拦截器来实现在查询时自动将数据库中加密的字段解密为明文。通过解析SQL语句并在执行前修改查询条件,将密文字段替换为解密表达式,实现了数据的透明解密。这种方法适用于需要对多个表中的相同字段进行解密的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mybatisPlus自定义拦截器

一开始数据库的数据是明文存储,后面某些数据需要变成密文保存在数据库,而且密文的字段在很多数据表中都存在。进行select操作时,把密文查询出来并转成明文。
1、使用切面,当接口获取到数据后,遍历数据找到密文字段,把密文解密得到明文
2、使用mybatisPlus自定义拦截器,在sql语句执行前拦截,把 字段 改成 IFNULL(AES_DECRYPT(UNHEX(字段), 密码),字段) AS 字段,sql语句可以解密得到明文。
下面是mybatisPlus自定义拦截器的代码:

@EnableTransactionManagement
@Configuration
public class MybatisPlusConfig {
    @Resource
    private DataScopeInterceptor dataScopeInterceptor;

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 数据权限过滤
        interceptor.addInnerInterceptor(dataScopeInterceptor);
        return interceptor;
    }
}
@Component
public class DataScopeInterceptor implements InnerInterceptor {
	private static Set<SelectItem> selectItemSet = new HashSet<>();
    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        String buildSql = boundSql.getSql();
        try {
            Statement statement = CCJSqlParserUtil.parse(buildSql);
            Select select = (Select) statement;
            processSelectBody(select.getSelectBody());
            PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
            mpBoundSql.sql(select.toString());
        } catch (JSQLParserException e) {
            throw ExceptionUtils.mpe("Failed to process, Error SQL: %s", e.getCause(), buildSql);
        } catch (BaseBusinessException be) {
            log.warn(be.getMessage());
        }
    }
    private void processSelectBody(SelectBody selectBody) throws BaseBusinessException, JSQLParserException {
        if (selectBody == null) {
            throw new BaseBusinessException(ResponseCodeEnum.IGNORE_DATA_SCOPE);
            // return;
        }
        if (selectBody instanceof PlainSelect) {
            processPlainSelect((PlainSelect) selectBody);
        } else if (selectBody instanceof WithItem) {
            WithItem withItem = (WithItem) selectBody;
            processSelectBody(withItem.getSelectBody());
        } else {
            SetOperationList operationList = (SetOperationList) selectBody;
            List<SelectBody> selectBodys = operationList.getSelects();
            if (CollectionUtils.isNotEmpty(selectBodys)) {
                for (SelectBody body : selectBodys) {
                    processSelectBody(body);
                }
            }
        }
    }
    private void proprocessPlainSelect(PlainSelect plainSelect) throws JSQLParserException {
        if(selectItemSet.size()>0) selectItemSet = new HashSet<>();
        FromItem fromItem = plainSelect.getFromItem();
        List<Join> joins = plainSelect.getJoins();
        processSelectColumns(plainSelect, fromItem);
        if (CollectionUtils.isNotEmpty(joins)) {
            for (Join join : joins) {
                if (join.isInner() || join.isFull() || join.isSimple()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                } else if (join.isLeft()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                } else if (join.isRight()) {
                    FromItem rightItem = join.getRightItem();
                    processSelectColumns(plainSelect, rightItem);
                }
            }
        }
        if (selectItemSet.size() == 0) return;
        List<String> filterItem = new ArrayList<>();
        List<SelectItem> selectItemList=selectItemSet.stream()
                .filter(e -> {
                    boolean found = !filterItem.contains(e.toString());
                    filterItem.add(e.toString());
                    return found;
                })
                .collect(Collectors.toList());
        if (selectItemList.size() > 0) {
            plainSelect.setSelectItems(selectItemList);
        }
    }
    // select时解密; *号根据具体的表替换成具体的字段
    private void processSelectColumns(PlainSelect plainSelect, FromItem fromItem) {
    	if (! (fromItem instanceof Table)) return;
        Table table = (Table) fromItem;

        for (SelectItem selectItem : plainSelect.getSelectItems()) {
        	// 1、做判断,不是需要解密的字段和*号就直接add
        	// 2、是需要解密的字段,则变成IFNULL(AES_DECRYPT(UNHEX(字段), 密码),字段) AS 字段,再add
        	// 3、*号则转换成具体的表字段,遍历表字段,是需要解密的字段则转换后add,不是就直接add。add前需要把字段String变成selectItem
        	// 最后。 sql语句会出现 table b;b.id bid、b.id、id;等情况,根据实际情况判断
        	selectItemSet.add(selectItem);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值