Java利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏
幾天前使用了Jackson對數(shù)據(jù)的自定義序列化。突發(fā)靈感,利用此方法來簡單實(shí)現(xiàn)接口返回?cái)?shù)據(jù)脫敏,故寫此文記錄。
核心思想是利用Jackson的StdSerializer,@JsonSerialize,以及自己實(shí)現(xiàn)的數(shù)據(jù)脫敏過程。
使用效果如下:
首先在需要進(jìn)行脫敏的VO字段上面標(biāo)注相關(guān)脫敏注解

調(diào)用接口即可看到脫敏效果

實(shí)現(xiàn)過程如下:
1. 定義脫敏的過程實(shí)現(xiàn)
/**
* Created by EalenXie on 2021/9/24 15:52
* 頂級的脫敏器
*/
public interface Desensitization<T> {
/**
* 脫敏實(shí)現(xiàn)
*
* @param target 脫敏對象
* @return 脫敏返回結(jié)果
*/
T desensitize(T target);
}
比如具體的手機(jī)號脫敏器實(shí)現(xiàn)
import com.github.Symbol;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by EalenXie on 2021/9/24 15:56
* 手機(jī)號脫敏器 默認(rèn)只保留前3位和后4位
*/
public class PhoneDesensitization implements StringDesensitization {
/**
* 手機(jī)號正則
*/
private static final Pattern DEFAULT_PATTERN = Pattern.compile("(13[0-9]|14[579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}");
/**
* 手機(jī)號脫敏 只保留前3位和后4位
*/
@Override
public String desensitize(String target) {
Matcher matcher = DEFAULT_PATTERN.matcher(target);
while (matcher.find()) {
String group = matcher.group();
target = target.replace(group, group.substring(0, 3) + Symbol.getSymbol(4, Symbol.STAR) + group.substring(7, 11));
}
return target;
}
}
2.定義脫敏注解,并指明了使用的序列化器,注解中聲明了使用的脫敏器實(shí)現(xiàn)
package com.github.annotation;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.github.desensitization.Desensitization;
import com.github.serializer.ObjectDesensitizeSerializer;
import java.lang.annotation.*;
/**
* Created by EalenXie on 2021/10/8 11:30
*/
@Target({ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = ObjectDesensitizeSerializer.class)
@Documented
public @interface Desensitize {
/**
* 脫敏器實(shí)現(xiàn)
*/
@SuppressWarnings("all")
Class<? extends Desensitization<?>> desensitization();
}
3. 實(shí)現(xiàn)定義的序列化器
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 com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.github.Symbol;
import com.github.annotation.Desensitize;
import com.github.desensitization.Desensitization;
import com.github.desensitization.DesensitizationFactory;
import com.github.desensitization.StringDesensitization;
import java.io.IOException;
/**
* Created by EalenXie on 2021/8/9 9:03
* 脫敏序列化器
*/
public class ObjectDesensitizeSerializer extends StdSerializer<Object> implements ContextualSerializer {
private transient Desensitization<Object> desensitization;
protected ObjectDesensitizeSerializer() {
super(Object.class);
}
public Desensitization<Object> getDesensitization() {
return desensitization;
}
public void setDesensitization(Desensitization<Object> desensitization) {
this.desensitization = desensitization;
}
@Override
public JsonSerializer<Object> createContextual(SerializerProvider prov, BeanProperty property) {
Desensitize annotation = property.getAnnotation(Desensitize.class);
return createContextual(annotation.desensitization());
}
@SuppressWarnings("unchecked")
public JsonSerializer<Object> createContextual(Class<? extends Desensitization<?>> clazz) {
ObjectDesensitizeSerializer serializer = new ObjectDesensitizeSerializer();
if (clazz != StringDesensitization.class) {
serializer.setDesensitization((Desensitization<Object>) DesensitizationFactory.getDesensitization(clazz));
}
return serializer;
}
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
Desensitization<Object> objectDesensitization = getDesensitization();
if (objectDesensitization != null) {
try {
gen.writeObject(objectDesensitization.desensitize(value));
} catch (Exception e) {
gen.writeObject(value);
}
} else if (value instanceof String) {
gen.writeString(Symbol.getSymbol(((String) value).length(), Symbol.STAR));
} else {
gen.writeObject(value);
}
}
}
4.代碼的設(shè)計(jì)說明

完整代碼可見 : https://github.com/EalenXie/jackson-desensitize
另附 基于Logback的日志脫敏方案(筆者認(rèn)為這可能是全網(wǎng)最簡單快捷的)
原理是利用Logback的自定義日志轉(zhuǎn)換器ClassicConverter
1. 自定義脫敏日志轉(zhuǎn)換器
import ch.qos.logback.classic.pattern.ClassicConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.github.desensitization.EmailDesensitization;
import com.github.desensitization.IDCardDesensitization;
import com.github.desensitization.PhoneDesensitization;
import com.github.desensitization.StringDesensitization;
import java.util.ArrayList;
import java.util.List;
/**
* @author EalenXie create on 2021/3/18 10:07
* 此Converter提供支持日志脫敏
* 1. 編寫此LogbackDesensitizeConverter
* 2. 正則脫敏 手機(jī)號/郵箱/身份證
*/
public class LogbackDesensitizeConverter extends ClassicConverter {
protected static final List<StringDesensitization> DESENSITIZATION_LIST = new ArrayList<>();
static {
// 手機(jī)號脫敏
DESENSITIZATION_LIST.add(new PhoneDesensitization());
// 郵箱脫敏
DESENSITIZATION_LIST.add(new EmailDesensitization());
// 身份證脫敏
DESENSITIZATION_LIST.add(new IDCardDesensitization());
}
@Override
public String convert(ILoggingEvent event) {
String content = event.getMessage();
try {
for (StringDesensitization desensitization : DESENSITIZATION_LIST) {
content = desensitization.desensitize(content);
}
} catch (Exception e) {
// ig
}
return content;
}
}
2. 啟動類為PatternLayout的靜態(tài)變量defaultConverterMap新增此自定義轉(zhuǎn)換器
import ch.qos.logback.classic.PatternLayout;
import com.github.filter.LogbackDesensitizeConverter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @author EalenXie create on 2020/11/24 14:16
*/
@EnableDiscoveryClient
@SpringBootApplication
public class ApiGatewayApplication {
public static void main(String[] args) {
// 日志處理方案 新增一個Logback的日志脫敏轉(zhuǎn)換器
PatternLayout.defaultConverterMap.put("m", LogbackDesensitizeConverter.class.getName());
SpringApplication.run(ApiGatewayApplication.class, args);
}
}
啟動后可以看到日志脫敏效果。

到此這篇關(guān)于利用Jackson序列化實(shí)現(xiàn)數(shù)據(jù)脫敏的文章就介紹到這了,更多相關(guān)Jackson序列化數(shù)據(jù)脫敏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java并發(fā)編程中使用Executors類創(chuàng)建和管理線程的用法
這篇文章主要介紹了Java并發(fā)編程中使用Executors類創(chuàng)建和管理線程的用法,文中舉了用其啟動線程和設(shè)置線程優(yōu)先級的例子,需要的朋友可以參考下2016-03-03
Mybatis傳單個參數(shù)和<if>標(biāo)簽同時使用的問題及解決方法
這篇文章主要介紹了Mybatis傳單個參數(shù)和<if>標(biāo)簽同時使用的問題及解決方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2018-05-05
java理論基礎(chǔ)Stream?reduce實(shí)現(xiàn)集合元素歸約
這篇文章主要為大家介紹了java理論基礎(chǔ)Stream?reduce實(shí)現(xiàn)集合元素歸約示例詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
SpringBoot項(xiàng)目中遇到的BUG問題及解決方法
這篇文章主要介紹了SpringBoot項(xiàng)目中遇到的BUG問題及解決方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11
Ubuntu16.04安裝部署solr7的圖文詳細(xì)教程
這篇文章主要為大家詳細(xì)介紹了Ubuntu16.04安裝部署solr7的圖文詳細(xì)教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07
Java方法重寫_動力節(jié)點(diǎn)Java學(xué)院整理
在Java和其他一些高級面向?qū)ο蟮木幊陶Z言中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類并不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要采用方法的重寫。方法重寫又稱方法覆蓋,下文給大家介紹java方法重寫及重寫規(guī)則,一起學(xué)習(xí)吧2017-04-04
SpringBoot導(dǎo)入mail依賴報(bào)錯問題解決
這篇文章主要介紹了SpringBoot導(dǎo)入mail依賴報(bào)錯問題解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10

