SpringBoot 实现数据脱敏

前言

数据脱敏是指对某些敏感信息通过脱敏规则进行数据的变形,实现敏感隐私数据的可靠保护。

数据脱敏常用规则有替换、重排、加密、截断、掩码

  • 替换:用其他字符或者符号替换原始数据中的字符或者符号,例如将手机号码中间四位替换为星号。
  • 重排:将原始数据中的字符或者符号重新排列,例如将身份证号码中的数字重新排列。
  • 加密:使用加密算法对原始数据进行加密,例如使用AES算法对银行卡号进行加密。
  • 截断:将原始数据中的一部分截取掉,例如只保留姓名的首字母。
  • 掩码:使用特定符号或者字符掩盖原始数据中的一部分,例如使用星号掩盖信用卡号码中的一部分数字。

Hutool 实现数据脱敏

hutool ——一个 Java 基础工具类,对文件、流、加密解密、转码、正则、线程、XML等JDK方法进行封装,组成各种 Util 工具类

官方文档:简介 | Hutool

引入依赖

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>

脱敏工具类

hutool 使用信息脱敏工具——DesensitizedUtil 实现脱敏操作

现阶段支持的脱敏数据类型包括:

  1. 用户id
  2. 中文姓名
  3. 身份证号
  4. 座机号
  5. 手机号
  6. 地址
  7. 电子邮件
  8. 密码
  9. 中国大陆车牌,包含普通车辆、新能源车辆
  10. 银行卡

自定义隐藏可以使用StrUtil.hide方法完成

代码实现

public class HutoolDesensitized {
    
    
    
    public static void main(String[] args) {
    
    
        String phone = "15888888888";
        System.out.println(DesensitizedUtil.mobilePhone(phone)); // 158****8888

        String idCard = "490508200001010001";
        System.out.println(DesensitizedUtil.idCardNum(idCard,4,4)); // 4905**********0001

        String password = "dddd3343ssxx";
        System.out.println(DesensitizedUtil.password(password)); // ************ 对于密码则只保留位数

        String bankCard = "8845600134008139446";
        System.out.println(DesensitizedUtil.bankCard(bankCard)); // 8845 **** **** *** 9446
    }
    
}

使用注解的方式

使用 SpringBoot 自带的 jackson 自定义序列化实现,在 json 进行序列化返回时,实现脱敏

定义枚举

public enum DesensitizationTypeEnum {
    
    
    // 自定义
    CUSTOM_RULE,
    // 用户id
    USER_ID,
    // 中文名
    CHINESE_NAME,
    // 身份证号
    ID_CARD,
    // 座机号
    FIXED_PHONE,
    // 手机号
    MOBILE_PHONE,
    // 地址
    ADDRESS,
    // 电子邮件
    EMAIL,
    // 密码
    PASSWORD,
    // 车牌
    CAR_LICENSE,
    //银行卡
    BANK_CARD
}

自定义序列化类

继承JsonSerializer,实现 ContextualSerializer 接口

@AllArgsConstructor
@NoArgsConstructor
public class DesensitizationSerialize extends JsonSerializer<String> implements ContextualSerializer {
    
    
    private DesensitizationTypeEnum type;

    private Integer startInclude;

    private Integer endExclude;

    @Override
    public void serialize(String str, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
    
    
        switch (type) {
    
    
            // 自定义类型脱敏
            case CUSTOM_RULE:
                jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude));
                break;
            // 用户名脱敏
            case USER_ID:
                jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId()));
                break;
            // 中文姓名脱敏
            case CHINESE_NAME:
                jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str)));
                break;
            // 身份证脱敏
            case ID_CARD:
                jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str), 4, 4));
                break;
            // 固定电话脱敏
            case FIXED_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str)));
                break;
            // 手机号脱敏
            case MOBILE_PHONE:
                jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str)));
                break;
            // 地址脱敏
            case ADDRESS:
                jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str), 8));
                break;
            // 邮箱脱敏
            case EMAIL:
                jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str)));
                break;
            // 密码脱敏
            case PASSWORD:
                jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str)));
                break;
            // 中国车牌脱敏
            case CAR_LICENSE:
                jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str)));
                break;
            // 银行卡脱敏
            case BANK_CARD:
                jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str)));
                break;
            default:
        }

    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
    
    
        if (beanProperty != null) {
    
    
            // 判断数据类型是否为String类型
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
    
    
                // 获取定义的注解
                Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class);
                // 为null
                if (desensitization == null) {
    
    
                    desensitization = beanProperty.getContextAnnotation(Desensitization.class);
                }
                // 不为null
                if (desensitization != null) {
    
    
                    // 创建定义的序列化类的实例并且返回,入参为注解定义的type,开始位置,结束位置。
                    return new DesensitizationSerialize(desensitization.type(), desensitization.startInclude(),
                            desensitization.endExclude());
                }
            }

            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

定义注解

@JsonSerialize 定义 json 序列化器

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = DesensitizationSerialize.class)
public @interface Desensitization {
    
    
    /**
     * 脱敏数据类型,在 CUSTOM_RULE 的时候,startInclude 和 endExclude 生效
     */
    DesensitizationTypeEnum type() default DesensitizationTypeEnum.CUSTOM_RULE;

    /**
     * 脱敏开始位置(包含)
     */
    int startInclude() default 0;

    /**
     * 脱敏结束位置(不包含)
     */
    int endExclude() default 0;
}

测试

定义一个测试类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestUser {
    
    

    @Desensitization(type = DesensitizationTypeEnum.MOBILE_PHONE)
    private String phone;

    @Desensitization(type = DesensitizationTypeEnum.EMAIL)
    private String email;

    @Desensitization(type = DesensitizationTypeEnum.CUSTOM_RULE,startInclude = 3, endExclude = 9)
    private String customEntity;
}

测试接口

@RestController
@RequestMapping
public class TestController {
    
    

    @GetMapping("/test")
    public TestUser testDesensitization() {
    
    
        TestUser testUser = new TestUser();
        testUser.setPhone("15888888888");
        testUser.setEmail("[email protected]");
        testUser.setCustomEntity("dfkdjf3434__495kdjf@@");
        return testUser;
    }
}

返回数据

image-20231008201531787

猜你喜欢

转载自blog.csdn.net/weixin_62726289/article/details/133689309