SpringBoot如何优雅地实现返回数据脱敏

简介:数据脱敏是一种常见的数据安全保护技术,可以在保护数据隐私的同时,保持数据的有效性和可用性。在 Spring Boot 中,我们可以使用注解的方式实现数据脱敏,使代码更加简洁、易于维护和扩展。

本文章将介绍使用注解的方式实现,在返回数据给前端的时候,根据给定的脱敏规则实现敏感数据脱敏操作,实现步骤非常简单,一起来看看吧!

  1. 引入hutool依赖

Hutool是一个小而全的Java工具类库,内含信息脱敏工具-DesensitizedUtil,这里我们需要用到DesensitizedUtil。还不了解Hutool工具类的朋友们可以看看官方文档 https://hutool.cn/docs

<!-- hutool工具类 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.16</version>
</dependency>
  1. 自定义注解
package com.poi.desensitize.annotation;

import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.poi.desensitize.enums.SensitizeRuleEnums;
import com.poi.desensitize.serializer.SensitiveJsonSerializer;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author hzd
 * @description 数据脱敏注解
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitize {
  SensitizeRuleEnums rule();
}
  1. 脱敏规则枚举类
    这里的部分脱敏规则都是依赖Hutool的DesensitizedUtil工具类,同时也可以自行定义脱敏规则
package com.poi.desensitize.enums;

import cn.hutool.core.util.DesensitizedUtil;
import java.util.function.Function;

/**
 * @author hzd
 * @description 数据脱敏枚举
 */
public enum SensitizeRuleEnums {
  /**
   * 用户id脱敏
   */
  USER_ID(s -> String.valueOf(DesensitizedUtil.userId())),

  /**
   * 中文姓名脱敏
   */
  CHINESE_NAME(DesensitizedUtil::chineseName),

  /**
   * 身份证脱敏
   */
  ID_CARD(s -> DesensitizedUtil.idCardNum(s, 3, 4)),

  /**
   * 固定电话
   */
  FIXED_PHONE(DesensitizedUtil::fixedPhone),

  /**
   * 手机号脱敏
   */
  MOBILE_PHONE(DesensitizedUtil::mobilePhone),

  /**
   * 地址脱敏
   */
  ADDRESS(s -> DesensitizedUtil.address(s, 8)),

  /**
   * 电子邮箱脱敏
   */
  EMAIL(DesensitizedUtil::email),

  /**
   * 密码脱敏
   */
  PASSWORD(DesensitizedUtil::password),

  /**
   * 中国车牌脱敏
   */
  CAR_LICENSE(DesensitizedUtil::carLicense),

  /**
   * 银行卡脱敏
   */
  BANK_CARD(DesensitizedUtil::bankCard);

  /**
   * 可自行添加其他脱敏策略.....
   */
  private final Function<String, String> sensitize;

  public Function<String, String> sensitize() {
	return sensitize;
  }

  SensitizeRuleEnums(Function<String, String> sensitize) {
    this.sensitize = sensitize;
  }
}
  1. 数据脱敏 JSON 序列化类
    SpringBoot 中默认使用 jackson 作为 JSON 序列化工具,我们只要在数据返回前台的序列化过程中获取到我们自定义注解(Sensitize) ,对有该注解的字段实现脱敏操作,这样前台看到的数据就是脱敏的啦
package com.poi.desensitize.serializer;

import cn.hutool.core.util.DesensitizedUtil;
import com.fasterxml.jackson.core.JsonGenerator;
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 com.poi.desensitize.annotation.Sensitize;
import com.poi.desensitize.enums.SensitizeRuleEnums;

import java.io.IOException;
import java.util.Objects;

/**
 * @author hzd
 * @description 序列化类作用:对返回前台的数据进行脱敏
 */
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {

  private SensitizeRuleEnums rule;

  @Override
  public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
    jsonGenerator.writeString(rule.sensitize().apply(value));
  }

  @Override
  public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
    Sensitize annotation = beanProperty.getAnnotation(Sensitize.class);
    if (Objects.nonNull(annotation) && Objects.equals(String.class, beanProperty.getType().getRawClass())) {
      this.rule = annotation.rule();
      return this;
    }
    return null;
  }
} 
  1. 测试对象
/**
 * @author hzd
 * @description 测试对象
 */
@Data
public class User {
  private Long id;

  private String name;

  @Sensitize(rule = SensitizeRuleEnums.EMAIL)
  private String email;

  @Sensitize(rule = SensitizeRuleEnums.PASSWORD)
  private String password;

  @Sensitize(rule = SensitizeRuleEnums.MOBILE_PHONE)
  private String phone;
}
  1. 测试接口
/**
 * @author hzd
 * @description 测试对象
 */
package com.poi.desensitize.controller;

import com.poi.desensitize.model.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author hzd
 * @description 测试类
 */
@RestController
public class TestController {


  @GetMapping("getUser")
  public User getUser(){
    User user = new User();
    user.setId(1L);
    user.setName("james");
    user.setEmail("[email protected]");
    user.setPhone("13211975672");
    user.setPassword("123456");

    return user;
  }
}
  1. 测试结果
    在这里插入图片描述

总结:
通过上述步骤,我们可以轻松地使用注解的方式实现数据脱敏,使代码更加简洁、易于维护和扩展,而且保护数据隐私的安全性。需要注意的是,数据脱敏只是一种较为简单的安全措施,对于更高级别的安全需求,还需要考虑使用加密等更加安全的手段来保护数据的安全性。

你可能感兴趣的:(SpringBoot,spring,boot,java,spring)