Skip to content

字段脱敏注解

注解定义

java

package org.elsfs.cloud.core.annotation;

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;

/**
 * 字段脱敏注解
 *
 * @author zeng
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
public @interface SensitiveBye {
  /**
   * 脱敏策略
   *
   * @return 脱敏策略
   */
  SensitiveType strategy() default SensitiveType.CUSTOM;
}
java

package org.elsfs.cloud.core.annotation;

import cn.hutool.core.util.DesensitizedUtil;
import java.util.function.Function;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

/**
 * 内置脱敏策略
 *
 * @author zeng
 */
@Getter
@RequiredArgsConstructor
public enum SensitiveType {

  /** 中文名字的敏感信息处理方式 */
  CHINESE_NAME(SensitiveByeHandle.CHINESE_NAME),

  /** 身份证号的敏感信息处理方式 */
  ID_CARD(SensitiveByeHandle.ID_CARD),

  /** 密码的敏感信息处理方式 */
  PASSWORD(SensitiveByeHandle.PASSWORD),

  /** 手机号的敏感信息处理方式 */
  MOBILE(SensitiveByeHandle.MOBILE),

  /** 电话号码的敏感信息处理方式 */
  PHONE(SensitiveByeHandle.PHONE),

  /** 电子邮件地址的敏感信息处理方式 */
  EMAIL(SensitiveByeHandle.EMAIL),

  /** 地址的敏感信息处理方式 */
  ADDRESS(SensitiveByeHandle.ADDRESS),

  /** 车牌号的敏感信息处理方式 */
  CAR_NUMBER(SensitiveByeHandle.CAR_NUMBER),

  /** 银行卡号的敏感信息处理方式 */
  BANK_CARD(SensitiveByeHandle.BANK_CARD),

  /** 自定义敏感信息的处理方式 */
  CUSTOM(SensitiveByeHandle.CUSTOM);

  /** 处理敏感信息的处理器 */
  private final SensitiveByeHandle handle;

  /**
   * 处理方法
   *
   * @param function 处理方法
   */
  public record SensitiveByeHandle(Function<String, String> function) {
    /** 中文姓名 */
    public static final SensitiveByeHandle CHINESE_NAME =
        new SensitiveByeHandle(DesensitizedUtil::chineseName);

    /** 身份证号 */
    public static final SensitiveByeHandle ID_CARD =
        new SensitiveByeHandle(s -> DesensitizedUtil.idCardNum(s, 3, 2));

    /** 密码 */
    public static final SensitiveByeHandle PASSWORD =
        new SensitiveByeHandle(DesensitizedUtil::password);

    /** 固话号码 */
    public static final SensitiveByeHandle MOBILE =
        new SensitiveByeHandle(DesensitizedUtil::fixedPhone);

    /** 手机号 */
    public static final SensitiveByeHandle PHONE =
        new SensitiveByeHandle(DesensitizedUtil::mobilePhone);

    /** 邮箱 */
    public static final SensitiveByeHandle EMAIL = new SensitiveByeHandle(DesensitizedUtil::email);

    /** 地址 */
    public static final SensitiveByeHandle ADDRESS =
        new SensitiveByeHandle(s -> DesensitizedUtil.address(s, 5));

    /** 银行卡号 */
    public static final SensitiveByeHandle BANK_CARD =
        new SensitiveByeHandle(DesensitizedUtil::bankCard);

    /** 车牌号 */
    public static final SensitiveByeHandle CAR_NUMBER =
        new SensitiveByeHandle(DesensitizedUtil::carLicense);

    /** 自定义策略 */
    public static final SensitiveByeHandle CUSTOM = new SensitiveByeHandle(s -> s);
  }
}

处理敏感信息拦截器

java

package org.elsfs.cloud.core.jackson.serializer;

import com.fasterxml.jackson.databind.introspect.Annotated;
import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
import org.elsfs.cloud.core.annotation.SensitiveBye;

/**
 * 处理敏感信息
 *
 * @author zeng
 */
public class SensitiveByeNopAnnotationIntrospector extends NopAnnotationIntrospector {
  @Override
  public Object findSerializer(Annotated am) {
    SensitiveBye annotation = am.getAnnotation(SensitiveBye.class);
    if (annotation != null) {
      return new SensitiveSerializer(annotation);
    }
    return null;
  }

  @Override
  public Object findDeserializer(Annotated am) {
    return super.findDeserializer(am);
  }
}

jackson配置

java

/**
 * jackson配置
 *
 * @author zeng
 */
@Configuration(proxyBeanMethods = false)
public class JacksonConfiguration {
  /**
   * ObjectMapper自定义配置
   *
   * @return ObjectMapper Builder
   */
  @Bean
  Jackson2ObjectMapperBuilderCustomizer objectMapperCustomizer() {
    return builder -> {
      builder.locale(Locale.CHINA);
      builder.timeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
      builder.simpleDateFormat(DatePattern.NORM_DATETIME_PATTERN);
      builder.serializerByType(Long.class, ToStringSerializer.instance);
      builder.modules(new com.fasterxml.jackson.datatype.jsr310.JavaTimeModule());
      // 覆盖部分
      builder.modules(new JavaTimeModule());
      builder.annotationIntrospector(new SensitiveByeNopAnnotationIntrospector());
    };
  }
}

如何使用

定义实体

java

/**
 * user
 *
 * @author zeng
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
  private String id;

  @SensitiveBye(strategy = SensitiveType.PHONE)
  private String phone;

  @SensitiveBye(strategy = SensitiveType.CHINESE_NAME)
  private String name;

  @SensitiveBye(strategy = SensitiveType.ID_CARD)
  private String idCard;

  @SensitiveBye(strategy = SensitiveType.PASSWORD)
  private String password;

  @SensitiveBye(strategy = SensitiveType.MOBILE)
  private String mobile;

  @SensitiveBye(strategy = SensitiveType.EMAIL)
  private String email;

  @SensitiveBye(strategy = SensitiveType.ADDRESS)
  private String address;

  @SensitiveBye(strategy = SensitiveType.BANK_CARD)
  private String bankCard;

  @SensitiveBye(strategy = SensitiveType.CAR_NUMBER)
  private String carNumber;

  @SensitiveBye(strategy = SensitiveType.CUSTOM)
  private String custom;
}

使用ObjectMapper的 bean 或者 new 一个ObjectMapper 并且添加拦截器

java
package org.elsfs.cloud.common.core.jackson;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elsfs.cloud.core.jackson.serializer.SensitiveByeNopAnnotationIntrospector;
import org.junit.jupiter.api.Test;

/**
 * 测试
 *
 * @author zeng
 */
@NoArgsConstructor
@Slf4j
public class SensitiveByeTest {
  @Test
  public void jsonUser() throws JsonProcessingException {

    //  添加的'test'自定义策略直接在注解中使用即可:@SensitiveBye("test")
    final ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setAnnotationIntrospector(new SensitiveByeNopAnnotationIntrospector());
    final DefaultSerializerProvider.Impl provider = new DefaultSerializerProvider.Impl();
    objectMapper.setSerializerProvider(provider);
    final User user =
        User.builder()
            .id("123")
            .phone("13212341234")
            .name("你好")
            .idCard("522322188012120123")
            .password("123456")
            .mobile("010-88880000")
            .email("abc@163.com")
            .address("北京市朝阳区十里堡123号")
            .bankCard("622312312341234123")
            .carNumber("京A-1234567")
            .custom("test自定义")
            .build();
    final String string = objectMapper.writeValueAsString(user);
    LOGGER.warn(string);
  }
}

版权声明