利用Jackson序列化实现数据脱敏
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用Jackson序列化实现数据脱敏相关的知识,希望对你有一定的参考价值。
参考技术A 先看下jackson的@JsonSerialize注解。@JsonSerialize是jackson提供自定义序列化方法的注解,它有个using 属性,指定自定义序列化的执行类;
例如:
先自定义一个序列化类
@JsonSerialize注解的Java类示例
我们知道,springMVC是通过jackson这个序列化框架,当响应头的Content-Type是application/json;charset=UTF-8时,对返回的vo转换为json对象;所以,利用jackson的注解,这样就可以实现脱敏,下面我们对这个注解做一层封装。
1.自定义序列化类,每当有需要脱敏的字段,例如,人名,邮箱,手机号等等,我们就创建一个这样的类,主要是制定一种脱敏的规则。
2.定义脱敏注解
@JacksonAnnotationsInside 表示将注解捆绑;当我们在字段注解@EmailDesensitize ,等价于@JsonSerialize(using = EmailDesensitization.class);
Symbol类
3.vo字段加注解
4.测试
5.结果
"name":"强强","someEmail":"13********@qq.com"
Jackson注解自定义数据脱敏策略
Jackson注解自定义数据脱敏策略
1.前言
有时候,我们返回给前端的数据需要脱敏,避免用户信息被泄漏,就像你点外卖一样,京东或淘宝购物一样,手机号,姓名这些字段是被脱敏后的,在这个大数据时代,用户的数据安全是及其重要的。我们如何对用户统一数据进行脱敏处理呢?如果我们自定义脱敏方式,使用一个工具类,被改字段传递进去,脱敏后返回新的字符串,那这样是很多地方需要手动去编写很多重复的代码,而且不利于维护,比如是单个bean,或者是list的时候还要去遍历一次list。有没有什么方法统一处理呢?我们定义好脱敏规则,只需要在需要脱敏的字段上加上一个注解即可。那当然是可以的
2.脱敏注解
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.springboot.example.desensitizer.handler.SensitiveJsonSerialize;
import com.springboot.example.desensitizer.enums.SensitiveStrategy ;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 脱敏注解
* @author compass
* @date 2022-12-11
* @since 1.0
**/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerialize.class)
public @interface Sensitive
SensitiveStrategy strategy();
3.定义好一套需要脱敏的规则
import java.util.function.Function;
/**
* 对需要特别脱敏的字段指定脱敏规则
* @author compass
* @date 2022-12-11
* @since 1.0
**/
public enum SensitiveStrategy
/**
* 对用户名进行脱敏,基于正则表达式实现
*/
USERNAME(s -> s.replaceAll("(\\\\S)\\\\S(\\\\S*)", "$1*$2")),
/**
* 对身份证进行脱敏
*/
ID_CARD(s -> s.replaceAll("(\\\\d4)\\\\d10(\\\\w4)", "$1****$2")),
/**
* 对电话号码进行脱敏
*/
PHONE(s -> s.replaceAll("(\\\\d3)\\\\d4(\\\\d4)", "$1****$2")),
/**
* 对地址进行脱敏
*/
ADDRESS(s -> s.replaceAll("(\\\\S3)\\\\S2(\\\\S*)\\\\S2", "$1****$2****")),
/**
* 对密码进行脱敏,全部加密即可
*/
PASSWORD(s -> "********");
private final Function<String, String> desensitizeSerializer;
SensitiveStrategy(Function<String, String> desensitizeSerializer)
this.desensitizeSerializer = desensitizeSerializer;
// 用于后续获取脱敏的规则,实现脱敏
public Function<String, String> desensitizeSerializer()
return desensitizeSerializer;
4.自定义JSON序列化
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.springboot.example.desensitizer.annotations.Sensitive;
import com.springboot.example.desensitizer.enums.SensitiveStrategy;
import java.io.IOException;
import java.util.Objects;
/**
* @author compass
* @date 2022-12-11
* @since 1.0
**/
public class SensitiveJsonSerialize extends JsonSerializer<String> implements ContextualSerializer
private SensitiveStrategy strategy;
// 在序列化时进行数据脱敏
@Override
public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException
jsonGenerator.writeString(strategy.desensitizeSerializer().apply(value));
// 获取注解上的属性
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider, BeanProperty property) throws JsonMappingException
Sensitive annotation = property.getAnnotation(Sensitive.class);
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
// 主要代码在这里,获取脱敏的规则
this.strategy = annotation.strategy();
return this;
return provider.findValueSerializer(property.getType(), property);
5.在实体类上标注对应的脱敏规则
@Data
@ToString
public class Employee
private Long id;
@Sensitive(strategy = SensitiveStrategy.USERNAME)
private String name;
private String email;
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String identity;
@Sensitive(strategy = SensitiveStrategy.PASSWORD)
private String password;
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phone;
private Date birthday;
private String jobNumber;
private Boolean verified;
@Sensitive(strategy = SensitiveStrategy.ADDRESS)
private String address;
5.写一个接口进行测试
@RestController
@RequestMapping("/sensitiveStrategy")
public class SensitiveStrategyController
@GetMapping("/v1/getSensitiveStrategy")
public ResponseResult<Employee> getSensitiveStrategy()
Employee employee = new Employee();
employee.setId(IdUtil.getSnowflakeNextId());
employee.setName("诸葛亮");
employee.setEmail("360369395@qq.com");
employee.setIdentity("522132188881017455X");
employee.setPassword("");
employee.setPhone("17785444960");
employee.setBirthday(new Date());
employee.setJobNumber(IdUtil.getSnowflake().nextIdStr());
employee.setVerified(false);
employee.setAddress("重庆市沙坪坝区大学城中路2-18号");
return ResponseResult.success("请求成功", employee);
调用我们写的测试接口,可以看到,我们的接口都做了脱敏处理
调用我们写的测试接口,可以看到,我们的接口都做了脱敏处理
以上是关于利用Jackson序列化实现数据脱敏的主要内容,如果未能解决你的问题,请参考以下文章