Background of 0.

Online projects involve a large number of query interfaces, there is the problem of phone number display in clear text is not compliant. If you modify the code logic related to the phone number field in the result returned by each interface, it will be more work and time consuming. Therefore, the design of telephone number encryption annotations, reduce the workload.

1. Introduce dependencies

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.18</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.8. RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.2.8. RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>
Copy the code

2. Owner information and owner information service

@Data
@AllArgsConstructor
public class CustomerInfo {

    private String name;

    private String phoneNum;
}

@Service
public class CustomerInfoService {

    @PhoneEncryptionForList(fields = "phoneNum", clazz = CustomerInfo.class)
    public List<CustomerInfo> listCustomerInfo(a) {
        return Arrays.asList(
                new CustomerInfo("Wang"."15112368569"),
                new CustomerInfo("Xiao li"."13652298565"),
                new CustomerInfo("Little arms"."18965653698"),
                new CustomerInfo("Little day"."13192558569")); }}Copy the code

3. Phone number encryption annotation, phone number encryption section class

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

    /** * Encryption field **@return* /
    String[] fields();

    /** * Encryption object type **@return* /Class<? > clazz(); }@Aspect
@Component
public class PhoneEncryptionForListAspect {

    private static final int PHONE_SIZE = 11;

    @AfterReturning(value = "@annotation(com.zzq.spring.phone.encryption.PhoneEncryptionForList)", returning = "result")
    public void doEncrypt(JoinPoint joinPoint, Object result) {
        if (result == null| |! (resultinstanceof List)) {
            System.out.println("result class type is not list, annotation is invalid");
            return;
        }

        List list = (List) result;
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        // Get the attribute value of the annotationMethod method = ((MethodSignature) joinPoint.getSignature()).getMethod(); PhoneEncryptionForList annotation = method.getAnnotation(PhoneEncryptionForList.class); String[] fields = annotation.fields(); Class<? > clazz = annotation.clazz();for (String field : fields) {
            try {
                // Reflection gets the set and get methods corresponding to the encrypted fields of the entity class
                char[] chars = field.toCharArray();
                chars[0] = (char) (chars[0] - 32);
                String setMethodName = "set" + new String(chars);
                String getMethodName = "get" + new String(chars);
                Method getMethod = clazz.getDeclaredMethod(getMethodName);
                Method setMethod = clazz.getDeclaredMethod(setMethodName, String.class);

                for(Object obj : list) { doEncryptPhone(getMethod, setMethod, obj); }}catch (Exception e) {
                System.out.println(field + " encrypt exception, " + e.getMessage());
                continue; }}}private static void doEncryptPhone(Method getMethod, Method setMethod, Object obj) throws Exception {
        Reflection calls the get method
        String originalPhone = (String)getMethod.invoke(obj);
        if(! StringUtils.hasText(originalPhone) || originalPhone.length() ! = PHONE_SIZE) { System.out.println("phone field value is blank or formal error");
            return;
        }

        String encryptedPhone = originalPhone.replaceAll("(\\d{3})\\d{4}(\\d{4})"."$1 * * * * $2");
        Reflection calls the set methodsetMethod.invoke(obj, encryptedPhone); }}Copy the code

4. The test class

@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.zzq.spring.phone.encryption")
public class TestApplication {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = newAnnotationConfigApplicationContext(TestApplication.class); CustomerInfoService customerInfoService = ctx.getBean(CustomerInfoService.class); List<CustomerInfo> afterPhoneEncryptCustomerInfos = customerInfoService.listCustomerInfo(); afterPhoneEncryptCustomerInfos.forEach(customerInfos -> { System.out.println(customerInfos); }); }}Copy the code

5. Results and conclusions

The encrypted notes only simple telephone encryption, implements the annotations can also add some properties to extend functionality annotations, such as increasing field format encryption rules of attribute value of the regular expression, such encryption field type (phone number, id card, etc.) and the way how many, the first encryption (middle) can handle according to the specific needs.