SpringBoot數(shù)據(jù)脫敏的實現(xiàn)示例
什么是數(shù)據(jù)脫敏
數(shù)據(jù)脫敏,也稱為數(shù)據(jù)的去隱私化或數(shù)據(jù)變形,是一種技術(shù)手段,用于對某些敏感信息通過特定的脫敏規(guī)則進行數(shù)據(jù)的變形,從而實現(xiàn)敏感隱私數(shù)據(jù)的可靠保護。這樣可以在開發(fā)、測試和其他非生產(chǎn)環(huán)境以及外包環(huán)境中安全地使用脫敏后的真實數(shù)據(jù)集。
數(shù)據(jù)脫敏的主要應用場景包括涉及客戶安全數(shù)據(jù)或商業(yè)性敏感數(shù)據(jù)的情況,例如身份證號、手機號、卡號、客戶號等個人信息都需要進行數(shù)據(jù)脫敏。數(shù)據(jù)脫敏的主要功能是通過使用數(shù)據(jù)脫敏產(chǎn)品,有效防止企業(yè)內(nèi)部對隱私數(shù)據(jù)的濫用,防止隱私數(shù)據(jù)在未經(jīng)脫敏的情況下從企業(yè)流出,滿足企業(yè)既要保護隱私數(shù)據(jù),同時又保持監(jiān)管合規(guī)的需求。
今天我們就用自定義注解的方式在我們的項目中實現(xiàn)數(shù)據(jù)脫敏。
@JsonSerialize
@JsonSerialize 是 Jackson 庫中的一個注解,用于在將 Java 對象序列化為 JSON 格式時指定如何進行自定義的序列化處理。Jackson 是一個流行的 Java 庫,用于處理 JSON 數(shù)據(jù)的序列化和反序列化。
@JsonSerialize 注解可以應用于字段、方法或類級別,允許我們自定義序列化過程。例如,我們可以通過 @JsonSerialize 注解將日期格式化為特定的字符串,或?qū)⒚杜e類型序列化為其名稱而不是值。
在使用 @JsonSerialize 注解時,我們可以使用 using 屬性來指定一個自定義的序列化器(Serializer)類,這個類需要繼承自 JsonSerializer,其中 T 是要序列化的對象的類型。通過這個自定義的序列化器,我們可以完全控制如何將 Java 對象轉(zhuǎn)換為 JSON 數(shù)據(jù)。
此外,@JsonSerialize 注解還有一些其他的屬性,如 include,用于指定序列化的范圍和作用規(guī)則(例如,只序列化非空的屬性)。
舉個簡單的例子,大家感受下:
@Data
public class CustomDateClass {
@JsonSerialize(using = CustomDateSerializer.class)
private Date myDate;
//自定義的日期序列化器
public static class CustomDateSerializer extends ToStringSerializer<Date> {
private static final long serialVersionUID = 1L;
public CustomDateSerializer() {
//傳遞null以使用默認日期格式
super(null);
}
//重寫 serialize 方法來定制日期的序列化過程,將其格式化為 "yyyy-MM-dd" 的字符串。
@Override
public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
String formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(value);
jgen.writeString(formattedDate);
}
}
}
接下來我們就使用自定義注解的方式,利用@JsonSerialize注解的特性來實現(xiàn)今天的數(shù)據(jù)脫敏功能。
自定義Jackson注解
需要自定義一個脫敏注解,一旦有屬性被標注,則進行對應的脫敏
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive {
//脫敏策略
SensitiveStrategy strategy();
}
定制脫敏策略
針對項目需求,定制不同字段的脫敏規(guī)則,比如手機號中間幾位用 * 替代:
/**
* 脫敏策略,枚舉類,針對不同的數(shù)據(jù)定制特定的策略
*/
public enum SensitiveStrategy
{
/**
* 姓名,第2位星號替換
*/
USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
/**
* 密碼,全部字符都用*代替
*/
PASSWORD(DesensitizedUtil::password),
/**
* 身份證,中間10位星號替換
*/
ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{4})", "$1** **** ****$2")),
/**
* 手機號,中間4位星號替換
*/
PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
/**
* 電子郵箱,僅顯示第一個字母和@后面的地址顯示,其他星號替換
*/
EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
/**
* 銀行卡號,保留最后4位,其他星號替換
*/
BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
/**
* 車牌號碼,包含普通車輛、新能源車輛
*/
CAR_LICENSE(DesensitizedUtil::carLicense);
private final Function<String, String> desensitizer;
SensitiveStrategy(Function<String, String> desensitizer)
{
this.desensitizer = desensitizer;
}
public Function<String, String> desensitizer()
{
return desensitizer;
}
}
定制JSON序列化實現(xiàn)
對標注注解@Sensitive的字段進行脫敏
/**
* 序列化注解自定義實現(xiàn)
* JsonSerializer<String>:指定String 類型,serialize()方法用于將修改后的數(shù)據(jù)載入
*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveStrategy strategy;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(strategy.desensitizer().apply(value));
}
/**
* 獲取屬性上的注解屬性
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, 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 prov.findValueSerializer(property.getType(), property);
}
}
脫敏工具類
/**
* 脫敏工具類
*/
public class DesensitizedUtil
{
/**
* 密碼的全部字符都用*代替,比如:******
*
* @param password 密碼
* @return 脫敏后的密碼
*/
public static String password(String password)
{
if (StringUtils.isBlank(password))
{
return StringUtils.EMPTY;
}
return StringUtils.repeat('*', password.length());
}
/**
* 車牌中間用*代替,如果是錯誤的車牌,不處理
*
* @param carLicense 完整的車牌號
* @return 脫敏后的車牌
*/
public static String carLicense(String carLicense)
{
if (StringUtils.isBlank(carLicense))
{
return StringUtils.EMPTY;
}
// 普通車牌
if (carLicense.length() == 7)
{
carLicense = StringUtils.hide(carLicense, 3, 6);
}
else if (carLicense.length() == 8)
{
// 新能源車牌
carLicense = StringUtils.hide(carLicense, 3, 7);
}
return carLicense;
}
}
定義Person類,對其數(shù)據(jù)脫敏
使用注解@Sensitive注解進行數(shù)據(jù)脫敏
@Data
public class Person {
/**
* 真實姓名
*/
@Sensitive(strategy = SensitiveStrategy.USERNAME)
private String realName;
/**
* 電話號碼
*/
@Sensitive(strategy = SensitiveStrategy.PHONE)
private String phoneNumber;
/**
* 身份證號碼
*/
@Sensitive(strategy = SensitiveStrategy.ID_CARD)
private String idCard;
}
模擬接口測試
以上4個步驟完成了數(shù)據(jù)脫敏的Jackson注解,下面寫個controller進行測試
@RestController
public class TestController {
@GetMapping("/test")
public Person test(){
Person user = new Person();
user.setRealName("阿Q說代碼");
user.setPhoneNumber("13588888888");
user.setIdCard("370213199204174235");
return user;
}
}
返回結(jié)果如下:

總結(jié)
到此這篇關(guān)于SpringBoot數(shù)據(jù)脫敏的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot數(shù)據(jù)脫敏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot2.x實現(xiàn)給Controller的RequestMapping添加統(tǒng)一前綴
這篇文章主要介紹了SpringBoot2.x實現(xiàn)給Controller的RequestMapping添加統(tǒng)一前綴,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02
各種格式的編碼解碼工具類分享(hex解碼 base64編碼)
這篇文章主要介紹了各種格式的編碼解碼工具類,集成Commons-Codec、Commons-Lang及JDK提供的編解碼方法2014-01-01
java計算自然數(shù)中的水仙花數(shù)的方法分享
這篇文章主要介紹了java計算自然數(shù)中的水仙花數(shù)的方法,需要的朋友可以參考下2014-03-03
Java如何獲取一個隨機數(shù) Java猜數(shù)字小游戲
這篇文章主要為大家詳細介紹了Java如何獲取一個隨機數(shù),類似猜數(shù)字小游戲,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-03-03
java打印從1到100的值(break,return斷句)
java 先寫一個程序,打印從1到100的值。之后修改程序,通過使用break關(guān)鍵詞,使得程序在打印到98時退出。然后嘗試使用return來達到相同的目的2017-02-02

