• SpringBoot 实现数据脱敏


    前言

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

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

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

    Hutool 实现数据脱敏

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

    官方文档:简介 | Hutool

    引入依赖

    <dependency>
        <groupId>cn.hutoolgroupId>
        <artifactId>hutool-allartifactId>
        <version>5.8.16version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    脱敏工具类

    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
        }
        
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    使用注解的方式

    使用 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
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    自定义序列化类

    继承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);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85

    定义注解

    @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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    测试

    定义一个测试类

    @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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    测试接口

    @RestController
    @RequestMapping
    public class TestController {
    
        @GetMapping("/test")
        public TestUser testDesensitization() {
            TestUser testUser = new TestUser();
            testUser.setPhone("15888888888");
            testUser.setEmail("dadfd_333@163.com");
            testUser.setCustomEntity("dfkdjf3434__495kdjf@@");
            return testUser;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    返回数据

    image-20231008201531787

  • 相关阅读:
    Swoole 进程模型分析
    1141 PAT Ranking of Institutions
    一款好用的PDF转翻页电子书网站
    Ubuntu 12.04增加右键命令:在终端中打开增加打开文件
    MindSpore导入CUDA算子
    fast planner代码解析--topo_prm.cpp
    Spring JDBC
    Leetcode643:子数组最大平均数 I
    vue:前端json数据 导出excel(Export2Excel)
    他用AI,抄袭了我的AI作品
  • 原文地址:https://blog.csdn.net/weixin_62726289/article/details/133689309