Custom annotation encryption, decryption and desensitization
Define custom annotations
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface PrivateData {
}Copy the code
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface PrivateDataMethod {
}Copy the code
Start by defining two custom annotations, privateData and privateDataMethod, to define the @target attribute as FIELD and METHOD, respectively.
Constructing AOP logic
-
Declare a pointcut
@Pointcut("@annotation(com.max.base.services.annotation.PrivateDataMethod)") public void annotationPointCut() { }Copy the code
Enter any method that adds the @privateDatamethod annotation.
-
Claim notification
@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 exception {}", throwable); } return responseObj; }Copy the code
Declare Aroud to inform the method of the input and output of the object, if the object is not a collection of direct encryption and decryption, otherwise split the collection, one by one operation
-
Processing encryption and decryption
@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); }}}}Copy the code
Get the list of fields for the object through reflection, execute the encryptValue() method on fields with the @privateData annotation and override the original Field with an encrypted string. The decryption logic is similar to encryption.
test
-
Identify the INSERT () method as the one that needs to be encrypted
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); }Copy the code
-
Annotate the fields in the incoming object that need to be encrypted
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...Copy the code
-
Call the INSERT method to view the data save result incoming object
{"createBy": "not happy ", "delFlag": "NOTDELETE"," Remarks ": "test encryption ", "tenantId": "996", "tenantName": "UpdateBy ":" Coke is not fun "}Copy the code
Database save object
-
The decryption test is not commented, so try it yourself
Desensitization logic
The desensitization logic is basically the same as encryption and decryption. It should be noted that desensitization annotations need to add type
@Documented
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Order(Ordered.HIGHEST_PRECEDENCE)
public @interface MaskingField {
MaskingTypeEnum type();
}Copy the code
Define the classification of desensitization in MaskingTypeEnum
Public enum MaskingTypeEnum {/* ID number */ ID_CARD, /* mobile number */ PHONE, /* ADDRESS */ ADDRESS, /* NAME */ NAME}Copy the code
Identifies the type of a field when MaskingTypeEnum is used
@MaskingField(type = MaskingTypeEnum.NAME)
private String cpName;Copy the code
Follow-up ~~bug~~ function everyone research, peace~
This article is published by OpenWrite!