注解方式实现字段加密解密以及脱敏

注解方式实现字段加密解密以及脱敏

1.创建方法注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FieldEncrypt {

    /**
     * 入参加密
     */
    boolean requestParam() default false;

    /**
     * 出参解密
     */
    boolean resultParam() default false;
}

2.创建属性注解

public @interface FieldHandling {

    /**
     * 是否加密
     */
    boolean encryption() default true;

    /**
     * 是否脱敏
     */
    boolean desensitization() default true;

    /**
     * 加密模式
     */
    EncryptionModeEnum encryptionMode() default EncryptionModeEnum.RSA;

    /**
     * 脱敏类型
     */
    DesensitizationTypeEnum type() default DesensitizationTypeEnum.ID_CARD;
}

3.加密相关类

@Getter
public enum EncryptionModeEnum {

    RSA(new RsaEncrypt());

    private final Encrypt encrypt;

    EncryptionModeEnum(Encrypt encrypt) {
        this.encrypt = encrypt;
    }
}

public class EncryptStrategy {

    public static Encrypt getEncryptMode(EncryptionModeEnum encryptionModeEnum) {
        return encryptionModeEnum.getEncrypt();
    }
}

public interface Encrypt {

    /**
     * 加密
     */
    String encrypt(String value);

    /**
     * 解密
     */
    String decode(String value);

}

public class RsaEncrypt implements Encrypt {

    /**
     * 默认的字符编码
     */
    private static final String DEFAULT_CHARSET = "utf-8";

    /**
     * 算法
     */
    private static final String ALGORITHM = "AES";

    /**
     * 算法/模式/填充
     **/
    private static final String CIPHER_MODE = "AES/ECB/PKCS5Padding";


    /**
     * key
     */
    public static final String AES_KEY = "xxxx";

    @Override
    public String encrypt(String value) {
        try {
            byte[] raw = AES_KEY.getBytes(DEFAULT_CHARSET);
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_MODE);
            cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
            byte[] encrypted = cipher.doFinal(value.getBytes(DEFAULT_CHARSET));
            return Base64.getEncoder().encodeToString(encrypted);
        } catch (Exception ex) {
            return null;
        }
    }

    @Override
    public String decode(String value) {
        try {
            byte[] raw = AES_KEY.getBytes(DEFAULT_CHARSET);
            SecretKeySpec secretKeySpec = new SecretKeySpec(raw, ALGORITHM);
            Cipher cipher = Cipher.getInstance(CIPHER_MODE);
            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
            // 先用base64解密
            byte[] encryptedArr = Base64.getDecoder().decode(value);
            byte[] original = cipher.doFinal(encryptedArr);
            return new String(original, DEFAULT_CHARSET);
        } catch (Exception ex) {
            return null;
        }
    }
}

4.脱敏字段枚举

public enum DesensitizationTypeEnum {
    ID_CARD,
    MOBILE,
    PASSWORD;
}

5.aop实现

@Component
@Slf4j
@Aspect
public class FieldEncryptAspect {

    @Pointcut("@annotation(com.xxx.annotation.FieldEncrypt)")
    public void fieldEncryptAspect() {
    }

    @Around("fieldEncryptAspect()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        FieldEncrypt annotation = method.getAnnotation(FieldEncrypt.class);
        //加密
        if (annotation.requestParam()) {
            this.fieldEncrypt(proceedingJoinPoint);
        }
        Object proceed = proceedingJoinPoint.proceed();
        //解密,脱敏
        if (annotation.resultParam()) {
            this.fieldDecode(data);
        }
        return proceed;
    }

    /**
     * 字段加密
     */
    public void fieldEncrypt(ProceedingJoinPoint proceedingJoinPoint) throws IllegalAccessException {
        Object[] args = proceedingJoinPoint.getArgs();
        for (Object arg : args) {
            Field[] fields = arg.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                FieldHandling fieldHandling = field.getAnnotation(FieldHandling.class);
                if (fieldHandling == null) {
                    continue;
                }
                if (fieldHandling.encryption()) {
                    //获取字段的名称和值
                    Object value = field.get(arg);
                    if (value == null) {
                        continue;
                    }
                    field.set(arg, EncryptStrategy.getEncryptMode(fieldHandling.encryptionMode()).encrypt(value.toString()));
                }
            }
        }
    }

    /**
     * 解密and脱敏
     */
    public void fieldDecode(Object data) throws IllegalAccessException {
        if (data == null) {
            return;
        }
        Field[] fields = data.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            FieldHandling fieldHandling = field.getAnnotation(FieldHandling.class);
            if (fieldHandling == null) {
                continue;
            }
            if (fieldHandling.encryption()) {
                //获取字段的名称和值
                Object value = field.get(data);
                if (value == null) {
                    continue;
                }
                //解密
                value = EncryptStrategy.getEncryptMode(fieldHandling.encryptionMode()).decode(value.toString());
                //脱敏
                value = this.fieldDesensitization(fieldHandling, value);
                field.set(data, value);
            }
        }
    }

    /**
     * 脱敏
     */
    public Object fieldDesensitization(FieldHandling fieldHandling, Object value) {
        if (fieldHandling.desensitization()) {
            if (Objects.equals(fieldHandling.type(), DesensitizationTypeEnum.ID_CARD)) {
                value = DesensitizedUtil.idCardNum(value.toString(), 1, 2);
            } else if (Objects.equals(fieldHandling.type(), DesensitizationTypeEnum.MOBILE)) {
                value = DesensitizedUtil.mobilePhone(value.toString());
            }
        }
        return value;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值