一开始数据库的数据是明文存储,后面某些数据需要变成密文保存在数据库,而且密文的字段在很多数据表中都存在。进行select操作时,把密文查询出来并转成明文。
1、使用切面,当接口获取到数据后,遍历数据找到密文字段,把密文解密得到明文
2、使用mybatisPlus自定义拦截器,在sql语句执行前拦截,把 字段 改成 IFNULL(AES_DECRYPT(UNHEX(字段), 密码),字段) AS 字段,sql语句可以解密得到明文。
下面是mybatisPlus自定义拦截器的代码:
@EnableTransactionManagement@Configurationpublic class MybatisPlusConfig { @Resource private DataScopeInterceptor dataScopeInterceptor; @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 数据权限过滤 interceptor.addInnerInterceptor(dataScopeInterceptor); return interceptor; }}
@Componentpublic class DataScopeInterceptor implements InnerInterceptor {private static Set 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 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 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 filterItem = new ArrayList<>(); List 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); } }
来源地址:https://blog.csdn.net/weixin_43381157/article/details/126764495