注解方式实现字段加密解密以及脱敏
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";
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);
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()));
}
}
}
}
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;
}
}