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);
        }
    }
Logo

本社区面向用户介绍CSDN开发云部门内部产品使用和产品迭代功能,产品功能迭代和产品建议更透明和便捷

更多推荐