SpringBoot实战:轻松实现接口数据脱敏

07-11 1694阅读

文章目录

  • 引言
  • 一、接口数据脱敏概述
    • 1.1 接口数据脱敏的定义
    • 1.2 接口数据脱敏的重要性
    • 1.3 接口数据脱敏的实现方式
    • 二、开发环境
    • 三、实现接口返回数据脱敏
      • 3.1 添加依赖
      • 3.2 创建自定义注解
      • 3.3 定义脱敏枚举类
      • 3.4 创建自定义序列化类
      • 四、测试
        • 4.1 编写测试代码
        • 4.2 测试
        • 五、总结

          SpringBoot实战:轻松实现接口数据脱敏

          引言

          在当今的信息化时代,数据安全尤为重要。接口返回数据脱敏是一种重要的数据保护手段,可以防止敏感信息通过接口返回给客户端,降低数据泄露的风险。本文旨在探讨如何在SpringBoot应用程序中实现接口返回数据脱敏。我们将介绍一种基于自定义注解结合Hutool脱敏工具类的方案,以实现SpringBoot中的接口返回数据脱敏。

          一、接口数据脱敏概述

          1.1 接口数据脱敏的定义

          接口数据脱敏是指在Web应用程序的API接口返回数据时,对包含敏感信息的字段进行处理,使其部分或全部信息被隐藏或替换,以防止敏感信息的泄露。这个过程通常不会改变数据的原始格式,而是通过特定的算法或规则,将敏感部分替换为特定字符(如星号*)或者保留部分信息。

          1.2 接口数据脱敏的重要性

          数据脱敏的重要性主要体现在以下几个方面:

          1. 保护用户隐私: 对于姓名、身份证号、手机号等个人敏感信息进行脱敏,可以有效保护用户隐私,防止信息被滥用。
          2. 遵守法律法规: 许多国家和地区都制定了严格的数据保护法规,如欧盟的GDPR和中国的《个人信息保护法》。实施数据脱敏有助于企业合规经营。
          3. 降低安全风险: 通过脱敏处理,即使数据不慎泄露,也能最大限度地减少敏感信息被盗用的风险。
          4. 支持数据共享: 在保护隐私的同时,脱敏数据仍然保留了一定的分析价值,有利于数据的安全共享和利用。

          1.3 接口数据脱敏的实现方式

          1. 手动脱敏:在业务逻辑层直接对敏感数据进行处理。这种方式灵活但容易遗漏,且代码重复率高。

          2. AOP(面向切面编程):通过切面拦截返回数据,统一处理敏感字段。这种方式可以集中管理脱敏逻辑,但可能影响性能。

          3. 自定义序列化器:利用JSON序列化框架(如Jackson)的自定义序列化器来处理敏感字段。这种方式性能较好,且与业务逻辑解耦。

          4. 注解+反射:通过自定义注解标记需要脱敏的字段,然后利用反射机制在运行时进行脱敏处理。这种方式使用简单,易于维护。

          本文将重点介绍如何结合自定义注解和Hutool工具类来实现接口数据脱敏。

          二、开发环境

          • JDK版本:JDK 17
          • Spring Boot版本:Spring Boot 3.2.2
          • 构建工具:Maven

            三、实现接口返回数据脱敏

            3.1 添加依赖

            首先在 pom.xml 文件中添加必要的依赖:

                    
            
                    cn.hutool
                    hutool-all
                    5.8.25
                
                
                
                    com.fasterxml.jackson.core
                    jackson-databind
                    2.9.2
                
            

            3.2 创建自定义注解

            接下来,我们创建一个自定义注解 @Desensitize:

            /**
             * 用于标记字段需要进行脱敏处理的注解
             *
             * @author shijun
             * @date 2024/07/09
             */
            @Retention(RetentionPolicy.RUNTIME)
            @Target(ElementType.FIELD)
            @JacksonAnnotationsInside
            @JsonSerialize(using = DesensitizeSerializer.class)
            public @interface Desensitize {
                /**
                 * 脱敏类型
                 */
                DesensitizeType type() default DesensitizeType.DEFAULT;
                /**
                 * 脱敏起始位置
                 */
                int startInclude() default 0;
                /**
                 * 脱敏结束位置
                 */
                int endExclude() default 0;
                
            }
            

            3.3 定义脱敏枚举类

            然后,定义枚举类 DesensitizeType 来定义字段的脱敏类型:

            /**
             * 脱敏类型枚举类
             */
            public enum DesensitizeType {
                /**
                 * 默认脱敏
                 */
                DEFAULT,
                /**
                 * 自定义脱敏
                 */
                CUSTOM_RULE,
                /**
                 * 手机号脱敏
                 */
                PHONE,
                /**
                 * 电子邮件脱敏
                 */
                EMAIL,
                /**
                 * 身份证号脱敏
                 */
                ID_CARD,
                /**
                 * 银行卡号脱敏
                 */
                BANK_CARD,
                /**
                 * 地址脱敏
                 */
                ADDRESS,
                /**
                 * 中文姓名脱敏
                 */
                CHINESE_NAME,
                /**
                 * 密码脱敏
                 */
                PASSWORD,
            }
            

            3.4 创建自定义序列化类

            Hutool支持的脱敏数据类型包括:

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

            整体来说,所谓脱敏就是隐藏掉信息中的一部分关键信息,用*代替。大家可以自己看一看DesensitizedUtil类中方法,其实就是replace方法和hide方法的使用,想要自定义规则进行隐藏可以仿照进行实现。

            /**
             * 脱敏序列化器,用于在序列化字符串时根据不同的脱敏类型进行数据脱敏。
             *
             * @author shijun
             * @date 2024/07/08
             */
            public class DesensitizeSerializer extends JsonSerializer implements ContextualSerializer {
                /**
                 * 脱敏类型,默认为DEFAULT
                 */
                private DesensitizeType type;
                /**
                 * 脱敏起始位置
                 */
                private int startInclude;
                /**
                 * 脱敏结束位置
                 */
                private int endExclude;
                public DesensitizeSerializer() {
                    this.type = DesensitizeType.DEFAULT;
                }
                public DesensitizeSerializer(DesensitizeType type) {
                    this.type = type;
                }
                /**
                 * 序列化字符串时调用,根据脱敏类型对字符串进行相应的脱敏处理。
                 *
                 * @param value       待序列化的字符串
                 * @param gen         JSON生成器,用于写入处理后的字符串
                 * @param serializers 序列化器提供者,用于获取其他序列化器
                 * @throws IOException 如果序列化过程中发生I/O错误
                 */
                @Override
                public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                    switch (type) {
                        case CUSTOM_RULE:
                            // 这里是对字符串的startInclude到endExclude字段进行隐藏处理,如果想要实现两端保留,可以考虑使用StrUtil的replace方法
                            gen.writeString(StrUtil.hide(value, startInclude, endExclude));
                            break;
                        case PHONE:
                            gen.writeString(DesensitizedUtil.mobilePhone(value));
                            break;
                        case EMAIL:
                            gen.writeString(DesensitizedUtil.email(value));
                            break;
                        case ID_CARD:
                            gen.writeString(DesensitizedUtil.idCardNum(value, 1, 2));
                            break;
                        case BANK_CARD:
                            gen.writeString(DesensitizedUtil.bankCard(value));
                            break;
                        case ADDRESS:
                            gen.writeString(DesensitizedUtil.address(value, 8));
                            break;
                        case CHINESE_NAME:
                            gen.writeString(DesensitizedUtil.chineseName(value));
                            break;
                        case PASSWORD:
                            gen.writeString(DesensitizedUtil.password(value));
                            break;
                        default:
                            gen.writeString(value);
                            break;
                    }
                }
                /**
                 * 根据上下文信息创建自定义的序列化器,用于处理带有@Desensitize注解的属性。
                 *
                 * @param prov     序列化器提供者,用于获取其他序列化器
                 * @param property 当前属性的信息,用于获取注解和属性类型
                 * @return 自定义的序列化器实例
                 */
                @Override
                public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) {
                    if (property != null) {
                        Desensitize annotation = property.getAnnotation(Desensitize.class);
                        if (annotation != null) {
                            this.type = annotation.type();
                            if (annotation.type() == DesensitizeType.CUSTOM_RULE) {
                                this.startInclude = annotation.startInclude();
                                this.endExclude = annotation.endExclude();
                            }
                        }
                    }
                    return this;
                }
            }
            

            代码分析:

            • serialize方法在序列化字符串时被调用,根据脱敏类型对字符串进行相应的脱敏处理。根据不同的脱敏类型,使用不同的处理方法对字符串进行脱敏,并将处理后的字符串写入JSON生成器中。
            • createContextual方法根据上下文信息创建自定义的序列化器,用于处理带有@Desensitize注解的属性。它通过获取注解中的脱敏类型和自定义规则的起始位置和结束位置,对实例进行相应的设置,并返回自定义的序列化器实例。

              这个序列化器的主要用途是在 JSON 序列化过程中自动对标记了 @Desensitize 注解的字段进行脱敏处理。

              四、测试

              4.1 编写测试代码

              1. 编写实体类
              @Data
              public class UserDTO {
                  /**
                   * 用户姓名
                   */
                  @Desensitize(type = DesensitizeType.CHINESE_NAME)
                  private String name;
                  /**
                   * 用户手机号
                   */
                  @Desensitize(type = DesensitizeType.PHONE)
                  private String phoneNumber;
                  /**
                   * 用户电子邮件地址
                   */
                  @Desensitize(type = DesensitizeType.EMAIL)
                  private String email;
                  /**
                   * 用户密码
                   */
                  @Desensitize(type = DesensitizeType.PASSWORD)
                  private String password;
                  /**
                   * 用户身份证号码
                   */
                  @Desensitize(type = DesensitizeType.ID_CARD)
                  private String idCard;
                  /**
                   * 用户银行卡号
                   */
                  @Desensitize(type = DesensitizeType.BANK_CARD)
                  private String bankCard;
                  /**
                   * 用户地址
                   */
                  @Desensitize(type = DesensitizeType.ADDRESS)
                  private String address;
                  /**
                   * 游戏名称
                   */
                  @Desensitize(type = DesensitizeType.CUSTOM_RULE, startInclude = 2, endExclude = 6)
                  private String gameName;
              }
              
              1. 编写测试接口
              @RestController
              @RequestMapping("/test")
              public class TestController {
                  
                  @GetMapping("/desensitize")
                  public UserDTO getUser() {
                      UserDTO userDTO = new UserDTO();
                      userDTO.setName("孙大圣");
                      userDTO.setEmail("shijun@163.com");
                      userDTO.setPhoneNumber("12345678901");
                      userDTO.setPassword("123456");
                      userDTO.setAddress("辽宁省盘锦市兴隆台区红村乡441号");
                      userDTO.setIdCard("447465200912089605");
                      userDTO.setBankCard("6217000000000000000");
                      userDTO.setGameName("超级无敌大铁锤");
                      return userDTO;
                  }
              }
              

              4.2 测试

              SpringBoot实战:轻松实现接口数据脱敏

              五、总结

              在本文中,我们探讨了在SpringBoot应用程序中实现数据脱敏的重要性,并提出了通过自定义注解结合Hutool脱敏工具类实现数据脱敏的解决方案。通过这个方案,我们能够有效地对敏感数据进行脱敏处理,从而保护用户隐私和数据安全,希望对大家有所帮助😊。

              SpringBoot实战:轻松实现接口数据脱敏

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]