首页 > 其他分享 >自定义注解实现加解密及脱敏

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

时间:2022-09-18 16:33:23浏览次数:129  
标签:String 自定义 加解密 private field 注解 public 脱敏


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 发布!

标签:String,自定义,加解密,private,field,注解,public,脱敏
From: https://www.cnblogs.com/RickTu/p/16705142.html

相关文章

  • 自定义typora主题样式
    目录自定义typora主题样式准备工作h1~h6标签内容居中修改默认字体样式自定义颜色名称,并修改选中字体的背景颜色添加背景右键菜单颜色mygithub.css自定义typora主题样式​......
  • 【3D Modeling Kit】建模服务,是否可以支持自定义图片上传?
    ​【3DModelingKit简介】3D建模服务(3DModelingKit)提供材质生成、3D物体建模、自动骨骼绑定和动作捕捉四大核心能力,提升内容制作效率,降低建模成本。材质生成:提供将......
  • 自定义监控MySQL主从状态
    自定义监控MySQL主从状态zabbix自定义监控Mysql主从状态和延迟目录自定义监控MySQL主从状态zabbix自定义监控Mysql主从状态和延迟监控Mysql主从状态主从同步主库配置从库......
  • zabbix自定义监控mysql主从状态和延迟
    zabbix自定义监控mysql主从状态和延迟目录zabbix自定义监控mysql主从状态和延迟zabbix自定义监控mysql主从状态zabbix自定义监控mysql主从延迟zabbix自定义监控mysql主......
  • 【django学习-11】模板3:自定义标签与过滤器
    前言:Django虽然内置了二十多种标签和六十多种过滤器,但是为了给Web开发者提供更好使用体验,Django也提供了自定义标签与过滤器的功能。当内置标签与过滤器满足不了实际......
  • zabbix自定义监控主从状态延迟与创建用户和组及权限管理
    1:zabbix监控主从部署mysql主从环境用到两台centos8的操作系统一台为master一台为slave[root@localhost~]#hostnamectlset-hostnamemaster[root@localhost~]#ba......
  • 4. 新版本的生产者API 带有自定义分区和回调函数的生产者
    1.开启进程[node123]systemctlstopfirewalld[node123]zkServer.shstart[node123]kafka-server-start.sh/opt/app/kafka-0.11.0.0/config/server.properties&[......
  • zabbix自定义监控mysql主从状态和延迟
    zabbix自定义监控mysql主从状态和延迟目录zabbix自定义监控mysql主从状态和延迟zabbix自定义监控mysql主从状态zabbix自定义监控mysql主从延迟zabbix自定义监控mysql主从......
  • CoreDNS实现自定义域名解析
    参考:https://support.huaweicloud.com/usermanual-cce/cce_01_0361.html一、修改CoreDNSHosts配置修改CoreDNS配置文件,将自定义域名添加到hosts中。例如将www.example.......
  • SpringBoot使用自定义注解+AOP+Redis实现接口限流
    为什么要限流系统在设计的时候,我们会有一个系统的预估容量,长时间超过系统能承受的TPS/QPS阈值,系统有可能会被压垮,最终导致整个服务不可用。为了避免这种情况,我们就需要对......