根据业务需求,要求多部分字段,进行加解密,想到实现方式,就是通过自定义的注解+AOP来实现
首先新建一个注解,注意ElementType.FIELD类型,说明这个注解只能作用在字段上
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedEncrypt {
}
在新建一个切面类
@Aspect
@Component
public class EncryptionAspect {@Resourceprivate EncryptionImpl encryptionService;//定义切点@Pointcut("within(com.bosssoft..*.*impl.*) && execution(* *(..))")public void pointCut(){}@Around("pointCut()")public Object encryptDecrypt(ProceedingJoinPoint joinPoint) throws Throwable {MethodSignature signature = (MethodSignature) joinPoint.getSignature();Method method = signature.getMethod();// 获取方法参数Object[] args = joinPoint.getArgs();Object entity = args[0];// 加密前encryptFieldsBeforeSave(entity);// 执行方法Object result = joinPoint.proceed(args);// 解密后if (result != null) {decryptFieldsAfterQuery((Object) result);}return result;}private void encryptFieldsBeforeSave(Object entity) throws IllegalAccessException {Class<?> clazz = entity.getClass();for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(NeedEncrypt.class)) {field.setAccessible(true);String value = (String) field.get(entity);if (value != null) {String encryptedValue = encryptionService.encrypt(value);field.set(entity, encryptedValue);}}}}private void decryptFieldsAfterQuery(Object entity) throws IllegalAccessException {Class<?> clazz = entity.getClass();for (Field field : clazz.getDeclaredFields()) {if (field.isAnnotationPresent(NeedEncrypt.class)) {field.setAccessible(true);String value = (String) field.get(entity);if (value != null) {String decryptedValue = encryptionService.decrypt(value);field.set(entity, decryptedValue);}}}}
}
这个类中定义了切面,包含所有的实现类,以及实现类中所有的方法
下一步创建这个切面类的实现类,用来实现一些方法,比如:具体的加解密算法
本加密算法采用的是AES
@Component
public class EncryptionImpl {private static final String SECRET_KEY = "your_secret_key";private static final String ALGORITHM = "AES";public String encrypt(String valueToEncrypt) {try {SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.ENCRYPT_MODE, secretKey);byte[] encryptedValue = cipher.doFinal(valueToEncrypt.getBytes(StandardCharsets.UTF_8));return Base64.getEncoder().encodeToString(encryptedValue);} catch (Exception e) {throw new RuntimeException("Encryption failed", e);}}public String decrypt(String encryptedValue) {try {SecretKeySpec secretKey = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM);Cipher cipher = Cipher.getInstance(ALGORITHM);cipher.init(Cipher.DECRYPT_MODE, secretKey);byte[] decodedValue = Base64.getDecoder().decode(encryptedValue);byte[] decryptedValue = cipher.doFinal(decodedValue);return new String(decryptedValue, StandardCharsets.UTF_8);} catch (Exception e) {throw new RuntimeException("Decryption failed", e);}}
}
注意的AES算法的密钥长度, 必须是 128 位(16 字节)、192 位(24 字节)或 256 位(32 字节)
示例:
新增数据:
查询数据: