本文章纯转载,如有侵权联系删除
SpringBoot如何优雅地实现返回数据脱敏
前言:数据脱敏是一种常见的数据安全保护技术,可以在保护数据隐私的同时,保持数据的有效性和可用性。在 Spring Boot 中,我们可以使用注解的方式实现数据脱敏,使代码更加简洁、易于维护和扩展。
目标: 实现在需要脱敏的字段上加上注解,返回前端时自动脱敏。
1. 创建Sensitize脱敏注解
package com.omni.admin.encryption.datamasking;import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitize {SensitizeRuleEnums rule();}
2. 配合使用SpringBoot 中jackson 作为 JSON 序列化工具,我们只要在数据返回前台的序列化过程中获取到我们自定义注解(Sensitize) ,对有该注解的字段实现脱敏操作。
package com.omni.admin.encryption.datamasking;import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;import java.io.IOException;
import java.util.Objects;public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {private SensitizeRuleEnums rule;@Overridepublic void serialize(String s, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {jsonGenerator.writeString(rule.sensitize().apply(s));}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) {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;}
}
3. 脱敏实现类
package com.omni.admin.encryption.datamasking;import cn.hutool.core.util.DesensitizedUtil;import java.util.function.Function;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;}
}
4. 使用该注解
只需要在需要脱敏的字段属性上 添加@Sensitize注解,并标识时哪一类即可。
/*** 用户电话*/@Sensitize(rule = SensitizeRuleEnums.MOBILE_PHONE)@Schema(title = "用户电话")private String phone;