美文网首页
自定义注解实现加解密及脱敏

自定义注解实现加解密及脱敏

作者: B1G_FISH | 来源:发表于2020-05-25 23:36 被阅读0次

    title: ep_自定义注解实现加解密及脱敏
    date: 2020-04-28 09:44


    定义自定义注解

    @Documented
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public @interface PrivateData {
    
    }
    
    @Documented
    @Target({ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public @interface PrivateDataMethod {
    
    }
    

    首先定义两个自定义注解,privateDataprivateDataMethod,分别将@Target属性定义为FIELDMETHOD

    构造AOP逻辑

    • 申明一个切入点
        @Pointcut("@annotation(com.max.base.services.annotation.PrivateDataMethod)")
        public void annotationPointCut() {
        }
    

    对所有添加@privateDataMethod注解的方法进行切入。

    • 申明通知
    @Around("annotationPointCut()")
        public Object around(ProceedingJoinPoint joinPoint) {
            Object responseObj = null;
            try {
                Object[] request = joinPoint.getArgs();
                for (Object object : request) {
                    if (object instanceof Collection) {
                        Collection collection = (Collection) object;
                        collection.forEach(var -> {
                            try {
                                handleEncrypt(var);
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            }
                        });
                    } else {
                        handleEncrypt(object);
                    }
                }
                responseObj = joinPoint.proceed();
                if (responseObj instanceof Collection) {
                    Collection collection = (Collection) responseObj;
                    collection.forEach(var -> {
                        try {
                            handleDecrypt(var);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    });
                } else {
                    handleDecrypt(responseObj);
                }
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                log.error("SecureFieldAop 异常{}", throwable);
            }
            return responseObj;
        }
    

    申明Aroud通知,对于方法输入输出的对象进行判断,如果是非集合对象则直接进行加解密操作,否则则拆分集合,逐一操作

    • 处理加解密
        /**
         * 处理加密
         * @param requestObj
         */
        private void handleEncrypt(Object requestObj) throws IllegalAccessException {
            if (Objects.isNull(requestObj)) {
                return;
            }
            Field[] fields = requestObj.getClass().getDeclaredFields();
            for (Field field : fields) {
                boolean hasSecureField = field.isAnnotationPresent(PrivateData.class);
                if (hasSecureField) {
                    Boolean accessible = field.isAccessible();
                    if (!accessible) {
                        field.setAccessible(true);
                    }
                    String plaintextValue = (String) field.get(requestObj);
                    String encryptValue = AseUtil.encrypt(plaintextValue, secretKey);
                    field.set(requestObj, encryptValue);
                    if (!accessible) {
                        field.setAccessible(false);
                    }
                }
            }
        }
    

    通过反射获取对象的Field列表,对于拥有@PrivateData注解的字段执行encryptValue()方法并用加密后的字符串覆盖原字段。
    解密逻辑与加密类似,不做赘述。

    测试

    • 标识insert()方法为需要加密的方法
    public interface CmTenantMapper {
        int deleteByPrimaryKey(Long id);
    
        @PrivateDataMethod
        int insert(CmTenant record);
    
        int insertSelective(CmTenant record);
    
        CmTenant selectByPrimaryKey(Long id);
    
        int updateByPrimaryKeySelective(CmTenant record);
    
        int updateByPrimaryKey(CmTenant record);
    }
    
    • 对传入对象中需要加密的字段添加注解
    public class CmTenant {
        private Long id;
        private String tenantId;
        @PrivateData
        private String tenantName;
        private String createBy;
        private Date createDate;
        private String updateBy;
        private Date updateDate;
        private String remarks;
        private Byte delFlag;
    //set get...
    
    • 调用insert方法查看数据保存结果
      传入对象
    {
      "createBy": "可乐可不乐",
      "delFlag": "NOTDELETE",
      "remarks": "测试加密",
      "tenantId": "996",
      "tenantName": "椅子团队出品",
      "updateBy": "可乐可不乐"
    }
    

    数据库保存对象

    • 解密测试不做注释,大家自行尝试

    脱敏逻辑

    脱敏逻辑与加解密基本一致,需要注意的一点是脱敏的注解需要添加type类型

    @Documented
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public @interface MaskingField {
        MaskingTypeEnum type();
    }
    

    MaskingTypeEnum中定义脱敏的分类

    public enum MaskingTypeEnum {
        /*身份证号码*/
        ID_CARD,
        /*手机号码*/
        PHONE,
        /*地址*/
        ADDRESS,
        /*姓名*/
        NAME
    }
    

    在使用是MaskingTypeEnum时标识字段的类型

        @MaskingField(type = MaskingTypeEnum.NAME)
        private String cpName;
    

    后续~~bug~~功能大家自行研究, peace~

    本文由博客一文多发平台 OpenWrite 发布!

    相关文章

      网友评论

          本文标题:自定义注解实现加解密及脱敏

          本文链接:https://www.haomeiwen.com/subject/vcepahtx.html