Java custom annotations to achieve data desensitization

Foreword:

To achieve log desensitization, annotation desensitization can also be achieved!

1. Annotations

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @program: sxsoft_expert
 * @ClassName DataMasking
 * @description: Data desensitization custom annotation
 * @author: handsome boy
 * @create: 2023-11-10 09:00
 * @Version 1.0
 **/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
public @interface DataMasking {

    /**
     * Data desensitization type
     */
    DataMaskingType type() default DataMaskingType.CUSTOM;

    /**
     * Desensitization start position (included)
     */
    int start() default 0;

    /**
     * Desensitization end position (not included)
     */
    int end() default 0;

}

2.log desensitization cycle coutroller adjusts DataMaskFor annotation desensitization coutroller adjusts DataMask method

import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import org.apache.commons.lang.ArrayUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Objects;

/**
 * @program: sxsoft_expert
 * @ClassName DataMaskingSerialize
 * @description: Custom serialization class
 * @author: handsome boy
 * @create: 2023-11-10 09:00
 * @Version 1.0
 **/

public class DataMaskingSerialize implements ContextualSerializer {

    private static Integer start;

    private static Integer end;


    public static TestEntity DataMaskFor(TestEntity entity){
        TestEntity obj = TestEntity.builder()
                .userId(entity.getUserId())
                .userName(entity.getUserName())
                .password(entity.getPassword())
                .address(entity.getAddress())
                .email(entity.getEmail())
                .fixedPhone(entity.getFixedPhone())
                .mobilePhone(entity.getMobilePhone())
                .carLicense(entity.getCarLicense())
                .bankCard(entity.getBankCard())
                .idCard(entity.getIdCard())
                .custom(entity.getCustom())
                .noMask(entity.getNoMask())
                .build();
        Field[] declaredFields = obj.getClass().getDeclaredFields();



        Arrays.asList(declaredFields).stream().forEach(fielfd -> {

            if(!ArrayUtils.isEmpty(fielfd.getAnnotations())){
// fielfd.set(obj, o);


                DataMasking annotation = (DataMasking)fielfd.getAnnotations()[0];
                DataMaskingType type = annotation.type();

                try {
                    if(!fielfd.isAccessible()){
                        fieldfd.setAccessible(true);
                    }

                    Object o = DataMask(fielfd.get(obj), type);
                    Class<?> type1 = fieldfd.getType();

                    if(type1.isAssignableFrom(Integer.class)){
                        fielfd.set(obj, Integer.valueOf(o.toString()));
                    }
                    else if(type1.isAssignableFrom(String.class) & amp; & amp; Objects.nonNull(o)){
                        fieldfd.set(obj, o.toString());
                    }else{
                        fieldfd.set(obj, o);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        });
        return obj;
    }

    public static Object DataMask(Object o ,DataMaskingType type) throws IOException {
        Object obj = null;
        String value = String.valueOf(o);
        switch (type) {
            //userId
            case USER_ID:
                obj = String.valueOf(DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.USER_ID));
                break;
            //Chinese name
            case CHINESE_NAME:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CHINESE_NAME));
                break;
            //ID number
            case ID_CARD:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ID_CARD));
                break;
            //landline
            case FIXED_PHONE:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.FIXED_PHONE));
                break;
            //Phone number
            case MOBILE_PHONE:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.MOBILE_PHONE));
                break;
            //address
            case ADDRESS:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.ADDRESS));
                break;
            //Mail
            case EMAIL:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.EMAIL));
                break;
            case BANK_CARD:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.BANK_CARD));
                break;
            //password
            case PASSWORD:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.PASSWORD));
                break;
            //Mainland China license plate number
            case CAR_LICENSE:
                obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.CAR_LICENSE));
                break;
// case IPV4:
// obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV4));
// break;
// case IPV6:
// obj = (DesensitizedUtil.desensitized(value, DesensitizedUtil.DesensitizedType.IPV6));
// break;
            //customize
            case CUSTOM:
                obj = CharSequenceUtil.hide(value, 3,5);
                break;
            default:
                break;
        }
        return obj;
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        if (Objects.nonNull(beanProperty)) {
            //Determine whether it is string type
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                DataMasking anno = beanProperty.getAnnotation(DataMasking.class);
                if (Objects.isNull(anno)) {
                    anno = beanProperty.getContextAnnotation(DataMasking.class);
                }
                if (Objects.nonNull(anno)) {
// return new DataMaskingSerialize(anno.type());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

3. Enumeration desensitization types

/**
 * @program: sxsoft_expert
 * @ClassName DataMaskingType
 * @description: Desensitization enumeration
 * @author: handsome boy
 * @create: 2023-11-10 09:00
 * @Version 1.0
 **/
public enum DataMaskingType {

        /**
         *User ID
         */
        USER_ID,
        /**
         * Chinese name
         */
        CHINESE_NAME,
        /**
         * ID number
         */
        ID_CARD,
        /**
         * Landline
         */
        FIXED_PHONE,
        /**
         * Phone number
         */
        MOBILE_PHONE,
        /**
         * address
         */
        ADDRESS,
        /**
         * Mail
         */
        EMAIL,
        /**
         * password
         */
        PASSWORD,
        /**
         * Mainland China license plate number
         */
        CAR_LICENSE,
        /**
         * Bank card number
         */
        BANK_CARD,
        /**
         * IPv4 address
         */
        IPV4,
        /**
         * IPv6 address
         */
        IPV6,
        /**
         * Custom type
         */
        CUSTOM;
}

4. Class

import lombok.*;
/**
 * @program: sxsoft_expert
 * @ClassName TestEntity
 * @description:
 * @author: handsome boy
 * @create: 2023-11-10 09:00
 * @Version 1.0
 **/
@Data
@Builder
@ToString
@AllArgsConstructor
@NoArgsConstructor
public class TestEntity {

    @DataMasking(type = DataMaskingType.USER_ID)
    private Integer userId;

    @DataMasking(type = DataMaskingType.CHINESE_NAME)
    private String userName;

    @DataMasking(type = DataMaskingType.ADDRESS)
    private String address;

    @DataMasking(type = DataMaskingType.ID_CARD)
    private String idCard;

    @DataMasking(type = DataMaskingType.FIXED_PHONE)
    private String fixedPhone;

    @DataMasking(type = DataMaskingType.MOBILE_PHONE)
    private String mobilePhone;

    @DataMasking(type = DataMaskingType.EMAIL)
    private String email;

    @DataMasking(type = DataMaskingType.PASSWORD)
    private String password;

    @DataMasking(type = DataMaskingType.CAR_LICENSE)
    private String carLicense;

    @DataMasking(type = DataMaskingType.BANK_CARD)
    private String bankCard;

// @DataMasking(type = DataMaskingType.IPV4)
// private String ipv4;
//
// @DataMasking(type = DataMaskingType.IPV6)
// private String ipv6;

    @DataMasking(type = DataMaskingType.CUSTOM,start = 3,end = 9)
    private String custom;

    /**
     * Fields that are not subject to data masking
     */
    private String noMask;

}

5.coutroller (log desensitization cycle coutroller adjusts DataMaskFor annotation desensitization coutroller adjusts DataMask method)

import com.example.demo11.service.impl.TestServiceImpl;
import com.example.demo11.uilt.TestEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Coutroller {

    @Autowired
    private TestServiceImpl testService;
    @RequestMapping(value="/test")
    public TestEntity test() {

        //Can only entities be returned directly?
        TestEntity entity;
        entity = testService.tt();
        return entity;

    }

}

Log desensitization is completely possible!

The knowledge points of the article match the official knowledge archives, and you can further learn related knowledge. Java Skill TreeAnnotationsBasic Grammar 139304 people are learning the system