实现了mybatisPlus的拦截器想要对敏感字段进行加解密,发现如果参数是queryWrapper的话无法取出其中的参数值和名称,各位大佬有什么办法吗?(只询问使用拦截器进行加解密的方法不讨论使用字段注解typeHandler的方法)
经过反复测试做出如下修改(此处只贴出关键代码如有错误请多多指正):

	@Override
    public Object intercept(Invocation invocation) throws Throwable {
        //拦截 ParameterHandler 的 setParameters 方法 动态设置参数
//        if (invocation.getTarget() instanceof ParameterHandler) {
//            encryptParamHandler(invocation);
//
//        }
        if (invocation.getTarget() instanceof StatementHandler) {
            encryptParamHandler(invocation);
        } else if (invocation.getTarget() instanceof ResultSetHandler) {
            return encryptResultHandler(invocation);
        }

        return invocation.proceed();
    }

	private void encryptParamHandler(Invocation invocation) {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        ParameterHandler parameterHandler = statementHandler.getParameterHandler();
        //获取绑定sql
        BoundSql boundSql = statementHandler.getBoundSql();

        // 反射获取 参数对像
        Object parameterObject = parameterHandler.getParameterObject();

        // 使用mybatis-plus提供的方法进行查询需要单独处理
        if (parameterObject instanceof MapperMethod.ParamMap) {
            Map param = (Map) parameterObject;
            int size = param.keySet().size() / 2;
            for (int i = 1; i <= size; i++) {
                String key = "param" + i;
                Object o = param.get(key);
                // QueryWrapper作为查询条件
                if (o instanceof QueryWrapper) {
                    QueryWrapper q = (QueryWrapper) o;
                    String sqlSegment = q.getExpression().getSqlSegment().toUpperCase();
                    this.columns.forEach(e -> {
                        String s = e + " =";
                        // 判断sql是否包含加密字段
                        if (sqlSegment.contains(s)) {
                        // 获取需要加密字段的值
                            String pKey = sqlSegment.split(s)[1].split("PARAMNAMEVALUEPAIRS.")[1].split("}")[0];
                            // 覆盖为加密后内容
                            q.getParamNameValuePairs().put(pKey, encrypt(q.getParamNameValuePairs().get(pKey).toString()));
                        }
                    });
                    // Map作为查询条件
                } else if (o instanceof Map) {
                    Map map = (Map) o;
//                    map.forEach((k, v) -> {
//                        if (needEncrypt(k.toString(), v)) {
//                            map.put(k, encrypt(v.toString()));
//                        }
//                    });
                    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
                    for (int j = 0; j < parameterMappings.size(); j++) {
                        ParameterMapping parameterMapping = parameterMappings.get(j);
                        if (parameterMapping.getMode() != ParameterMode.OUT) {
                            String propertyName = parameterMapping.getProperty();
                            String mapKey = propertyName.replaceFirst("__frch_v_", "__frch_k_");
                            if (map.containsKey(propertyName) && needEncrypt(propertyName,map.get(propertyName).toString())){
                                map.put(propertyName, encrypt(map.get(propertyName).toString()));

                            }else if (boundSql.hasAdditionalParameter(propertyName)
                                    && boundSql.hasAdditionalParameter(mapKey)
                                    && needEncrypt(boundSql.getAdditionalParameter(mapKey).toString(), boundSql.getAdditionalParameter(propertyName))) {
                                boundSql.setAdditionalParameter(propertyName, encrypt(boundSql.getAdditionalParameter(propertyName).toString()));
                            }
                        }
                    }

                    // 实体类作为查询条件
                } else if (Objects.nonNull(o)) {
                    BeanMap beanMap = BeanMap.create(o);
                    beanMap.forEach((k, v) -> {
                    //判断是否需要加密,进行加密
                        if (needEncrypt(k.toString(), v)) {
                            beanMap.put(k, encrypt(v.toString()));
                        }
                    });
                }
            }
        } else if (Objects.nonNull(parameterObject)) {
            BeanMap beanMap = BeanMap.create(parameterObject);
            beanMap.forEach((k, v) -> {
            //判断是否需要加密,进行加密
                if (needEncrypt(k.toString(), v)) {
                    beanMap.put(k, encrypt(v.toString()));
                }
            });
        }

    }
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐