• 库表字段加密存储,查询解密


    项目上有国密需求,要求重要数据得加密存储到数据库,页面是解密展示。因为表操作都是通过dao层去处理的,所以考虑直接在dao层拦截处理有加密注解的字段从而满足加解密需求。

    首先需要创建个加密注解,在需要加密的字段上加上该注解,然后在拦截器那里判断是否存在该注解,有的话即进行加密处理即可,查询时,判断值是否存在加密标识的,有就进行解密即可啦。贴代码:

    public class EncryptInterceptor implements MethodInterceptor {
    
        private final IDataCryptor encryptUtil;
    
        public EncryptInterceptor(IDataCryptor encryptUtil) {
            this.encryptUtil = encryptUtil;
        }
    
        @Override
        public Object invoke(MethodInvocation invocation) throws Throwable {
            Method method = invocation.getMethod();
            //方法是否有加解密注解,如果有的话,返回值为String、List等类型时需要解密返回。
            EncryptField encryptField = method.getAnnotation(EncryptField.class);
            boolean hasEncryptField = false;
            if (encryptField != null){
                hasEncryptField = true;
            }
            encrypt(invocation);
            Object returnParam = invocation.proceed();
            return decrypt(returnParam, hasEncryptField);
        }
    
        /**
         * 加密
         */
        public void encrypt(MethodInvocation invocation){
            Object[] params = invocation.getArguments();
            Method method = invocation.getMethod();
            Annotation[][] annotations = method.getParameterAnnotations();
            if (params.length != 0) {
                for (int i = 0; i < params.length; i++) {
                    Object o = params[i];
                    if (o != null) {
                        boolean hasEncryptField =false;
                        Annotation[] paramAnn = annotations[i];
                        for (Annotation annotation : paramAnn) {
                            //判断当前参数是否有注解为EncryptField
                            if (annotation.annotationType().equals(EncryptField.class)) {
                               hasEncryptField = true;
                               break;
                            }
                        }
                        if (o instanceof String) {
                            //没有加密注解,跳过
                            if (!hasEncryptField) {
                                continue;
                            }
                            params[i] = handlerString(o, true);
                        } else {
                            params[i] = handler(o, true, hasEncryptField);
                        }
                    }
                }
            }
        }
    
        /**
         * 解密
         * @param  hasEncryptField 返回参数是String、List等类型时,是否解密。
         */
        public Object decrypt(Object obj, boolean hasEncryptField){
            if (obj != null) {
                if (obj instanceof String && hasEncryptField) {
                    return handlerString(obj, false);
                } else {
                    return handler(obj, false, hasEncryptField);
                }
            }
            return obj;
        }
    
        /**
         * 处理String类型的请求、响应参数
         * @param obj
         * @param isEncrypt
         * @return
         */
        private Object handlerString (Object obj, boolean isEncrypt){
            if (Objects.isNull(obj)) {
                return obj;
            }
            String realValue = String.valueOf(obj);
            if (isEncrypt && !encryptUtil.isEncrypted(realValue)) {
                obj = encryptUtil.encrypt(realValue);
            } else if (!isEncrypt && encryptUtil.isEncrypted(realValue)) {
                obj = encryptUtil.decrypt(realValue);
            }
            return obj;
        }
    
        /**
         * 加密Object 类型的参数
         * @param obj
         * @param isEncrypt
         * @param hasEncryptField  请求、返回参数是List等类型时否需要加解密。
         * @return
         */
        private Object handler(Object obj, boolean isEncrypt, boolean hasEncryptField){
            if (Objects.isNull(obj)) {
                return null;
            }
            if (obj instanceof Collection) {
                Collection old = CheckUtil.cast(obj);
                Collection result;
                if (old instanceof List) {
                    result = new ArrayList<>();
                } else {
                    result = new LinkedHashSet<>();
                }
                for (Object o : old) {
                    result.add(handler(o, isEncrypt, hasEncryptField));
                }
                return result;
            }else if (obj instanceof Map) {
                Map old = CheckUtil.cast(obj);
                Map result = new LinkedHashMap<>();
                for(Map.Entry ent : old.entrySet()) {
                    result.put(ent.getKey(), handler(ent.getValue(), isEncrypt, hasEncryptField));
                }
                return result;
            }else if (obj.getClass().isArray()) {
                int len = Array.getLength(obj);
                for(int ix = 0; ix < len; ++ix)
                {
                    Object elem = Array.get(obj, ix);
                    Array.set(obj, ix, handler(elem, isEncrypt, hasEncryptField));
                }
                return obj;
            }else if (obj instanceof Optional){
                Optional old=CheckUtil.cast(obj);
                Optional result = old;
                if (old.isPresent()){
                    Object rvalue = handler(old.get(), isEncrypt, hasEncryptField);
                    result = Optional.of(rvalue);
                }
                return result;
            } else if (obj instanceof Slice){
                Slice old = CheckUtil.cast(obj);
                Slice result = old;
                if(old.hasContent()) {
                    //如果是Slice类型,且有内容,则一定是List类型值
                    Object content = old.getContent();
                    content = handler(content, isEncrypt, hasEncryptField);
                    List data=CheckUtil.cast(content);
                    result = new PageImpl<>(data, old.getPageable(), data.size());
                }
                return result;
            } else if (obj instanceof String && hasEncryptField){
                return handlerString(obj, isEncrypt);
            } else if (!isBaseType(obj)){
                Object result = obj;
                if (!isEncrypt && result instanceof EncryptCloneable){
                    result = ((EncryptCloneable) result).clone();
                }
                handlerObject(result,isEncrypt);
                return result;
            }
            return obj;
        }
    
        private void handlerObject(Object obj, boolean isEncrypt){
            if (Objects.isNull(obj)) {
                return ;
            }
            List fields = getAllField(obj);
            for (Field field : fields) {
                boolean hasEncryptField = field.isAnnotationPresent(EncryptField.class);
                if (hasEncryptField) {
                    try{
                        field.setAccessible(true);
                        String realValue = (String) field.get(obj);
                        if (StringUtils.isNotBlank(realValue)) {
                            String value = realValue;
                            if (isEncrypt && hasEncryptField && !encryptUtil.isEncrypted(realValue)) {
                                value = encryptUtil.encrypt(realValue);
                            } else if (!isEncrypt && hasEncryptField && encryptUtil.isEncrypted(realValue)) {
                                value = encryptUtil.decrypt(realValue);
                            }
                            field.set(obj, value);
                        }
                    }catch(Exception e){
                        // 如果处理出错,则不改变值
                        log.warn("对字段" + field.getName() + "处理加解密时出错:", e);
                    }
                }
            }
        }
    
        private static List getAllField(Object model) {
            Class clazz = model.getClass();
            List fields = new ArrayList<>();
            //只要父类存在,就获取其类的属性到集合
            while (clazz != null) {
                fields.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
                //获取其父类
                clazz = clazz.getSuperclass();
            }
            return fields;
        }
    
        /**
         * 检查是否基础类型,这些不做加解密处理
         *
         * @param obj
         * @return
         */
        private boolean isBaseType(Object obj)
        {
            if(obj.getClass().isPrimitive()) {
                return true;
            }
            return obj instanceof Boolean
                    || obj instanceof Byte
                    || obj instanceof Character
                    || obj instanceof Short
                    || obj instanceof Integer
                    || obj instanceof Long
                    || obj instanceof Float
                    || obj instanceof Double
                    || obj instanceof Date;
        }
    } 

  • 相关阅读:
    清除Ubuntu系统中的无法启动的Ubuntu 24实例
    后河水利枢纽重力坝整体设计(说明书+计算书+文献综述+外文翻译及原文+cad图纸 )
    【DL with Pytorch】第 2 章 : 神经网络的构建块
    np.partition介绍
    VUE render函数使用和详解
    ardupilot 安装gcc-arm-none-eabi编译工具
    mysql安装完全排坑指南
    C++多线程学习
    【面试题】如何理解 前端设计模式-测策略模式?
    噢!查重原来是这样实现的啊!
  • 原文地址:https://blog.csdn.net/U2133048/article/details/134034306