最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java數(shù)據(jù)脫敏實(shí)現(xiàn)的方法總結(jié)

 更新時(shí)間:2023年07月25日 11:02:10   作者:十年培訓(xùn)經(jīng)驗(yàn)的菜包  
數(shù)據(jù)脫敏,指的是對某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù),本文主要是對后端數(shù)據(jù)脫敏實(shí)現(xiàn)的簡單總結(jié),希望對大家有所幫助

什么是數(shù)據(jù)脫敏

數(shù)據(jù)脫敏,指的是對某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。摘自百度百科數(shù)據(jù)脫敏。

對數(shù)據(jù)進(jìn)行脫敏的操作一般是不可逆的。

脫敏內(nèi)容

一般來說,脫敏內(nèi)容包含但不限于各種隱私數(shù)據(jù)或商業(yè)性敏感數(shù)據(jù),如身份證號、手機(jī)、郵箱、營業(yè)執(zhí)照、銀行卡號等信息,具體要求需要根據(jù)不同公司業(yè)務(wù)而定。

脫敏場景

前端頁面內(nèi)容

我司系統(tǒng)都是前后端分離的系統(tǒng),脫敏方案都是在序列化層面來做,具體的實(shí)現(xiàn)也是基于各序列化庫,如jackson、fastjson。

Jackson實(shí)現(xiàn)

Jackson需要自定義一個(gè)序列化器

public class JacksonDataMaskSerializer extends StdSerializer<String> implements ContextualSerializer {
    //脫敏策略枚舉
 ? ?private DataMaskType dataMask;
 ? ?protected JacksonDataMaskSerializer() {
 ? ? ? ?super(String.class);
 ?  }
?
 ? ?@Override
 ? ?public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
 ? ? ? ?JacksonDataMask jacksonDataMask = property.getAnnotation(JacksonDataMask.class);
 ? ? ? ?if (jacksonDataMask != null && String.class.equals(property.getType().getRawClass())){
 ? ? ? ? ? ?dataMask = jacksonDataMask.maskType();
 ? ? ? ? ? ?return this;
 ? ? ?  }
 ? ? ? ?return prov.findContentValueSerializer(property.getType(),property);
 ?  }
?
 ? ?@Override
 ? ?public void serialize(String value, JsonGenerator gen, SerializerProvider provider) throws IOException {
 ? ?    //執(zhí)行脫敏
 ? ? ? ?String resultValue = dataMask.getStrategy().process(value,dataMask.getParams());
 ? ? ? ?gen.writeString(resultValue);
 ?  }
}

由于不同字段需要使用的脫敏規(guī)則是不同的,所以直接使用@JsonSerialize(contentUsing = JacksonDataMaskSerializer.class)并沒有什么意義,我們需要通過自定義Jackson的注解,來實(shí)現(xiàn)一個(gè)Serializer滿足不同脫敏工作,自定義注解如下

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = JacksonDataMaskSerializer.class)
public @interface JacksonDataMask {
?
 ? ?/**
 ? ? * 脫敏策略
 ? ? */
 ? ?DataMaskType maskType() default DataMaskType.Default;
}

可以看到,使用@JacksonAnnotationsInside注解,來實(shí)現(xiàn)Jackson的自定義注解功能,這樣即可滿足不同字段的脫敏要求,使用姿勢如下:

@Data
public class DemoVo{
 ? ?@JacksonDataMask(maskType = DataMaskType.Phone)
    private String phone;
 ? ?@JacksonDataMask(maskType = DataMaskType.Mail)
    private String email;
}

至于脫敏策略規(guī)則枚舉,非常簡單,就不寫了,無非就是不同策略對字段值的部分字符替換成特殊字符,常見的如”*“;

Fastjson實(shí)現(xiàn)

Fastjson的實(shí)現(xiàn)與Jackson類似,也是自定義序列化攔截器,讀取字段上注解,然后使用注解策略進(jìn)行脫敏處理,具體實(shí)現(xiàn)略。

導(dǎo)出數(shù)據(jù)內(nèi)容

常見導(dǎo)出數(shù)據(jù)的形式為導(dǎo)出excel,使用的導(dǎo)出excel工具庫如easyexcel、easypoi等,此處以easyexcel為例。

我們同樣需要自定義一個(gè)注解,如下:

public @interface ExcelDataMask {
?
 ? ?/**
 ? ? * 脫敏策略
 ? ? */
 ? ?DataMaskType maskType() default DataMaskType.Default;
}

看起來是不是與前面介紹序列化庫時(shí)自定義的注解一樣,其實(shí)直接使用前面的也沒問題,本質(zhì)上是標(biāo)志該字段的數(shù)據(jù)需要脫敏,以便不同實(shí)現(xiàn)的代碼可以識別。

有了自定義注解后,按照Excel官方demo,并在DTO字段上進(jìn)行注解。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class DemoItemDto {
?
 ? ?@ExcelProperty("手機(jī)號碼")
 ? ?@ExcelDataMask(maskType=DataMaskType.PHONE)
 ? ?private String phone;
}
EasyExcel.write("/demo.xlsx", DemoItemDto.class).registerWriteHandler(new CellWriteHandler() {
 ? ? ? ? ? ?@Override
 ? ? ? ? ? ?public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData<?> cellData, Cell cell, Head head, Integer relativeRowIndex, Boolean isHead) {
 ? ? ? ? ? ? ? ?if (isHead){
 ? ? ? ? ? ? ? ? ? ?//head不需要脫敏
 ? ? ? ? ? ? ? ? ? ?return;
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?ExcelDataMask excelDataMask = head.getField().getAnnotation(ExcelDataMask.class);
 ? ? ? ? ? ? ? ?if (excelDataMask == null) {
 ? ? ? ? ? ? ? ? ? ?return;
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?DataMaskType dataMaskType = excelDataMask.maskType();
 ? ? ? ? ? ? ? ?if (dataMaskType == null) {
 ? ? ? ? ? ? ? ? ? ?return;
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ? ? ?String stringValue = cellData.getStringValue();
 ? ? ? ? ? ? ? ?if (StrUtil.isNotBlank(stringValue)) {
 ? ? ? ? ? ? ? ?    //數(shù)據(jù)脫敏后重新寫入
 ? ? ? ? ? ? ? ? ? ?cellData.setStringValue(dataMaskType.process(stringValue));
 ? ? ? ? ? ? ?  }
 ? ? ? ? ?  }
 ? ? ?  }).sheet("模板").doWrite(list);

至此,一個(gè)簡單的excel導(dǎo)出內(nèi)容脫敏注解就完成了。

系統(tǒng)日志內(nèi)容

在有嚴(yán)格安全規(guī)范要求公司,系統(tǒng)運(yùn)行時(shí)打印的日志內(nèi)容也是需要脫敏的。

常見的日志框架無非是logback、log4j這些(slf4j只是一個(gè)門面,不提供具體日志實(shí)現(xiàn)),基本上使用方法最終都是一句log.xx來實(shí)現(xiàn)打印。此處簡單以打印json字符串為例

log.info("內(nèi)容:{}",JSON.toJsonString(dto));

一般來說,有兩種方案。

方案一(不推薦)

自定義dto轉(zhuǎn)json字符串的方案,使用json序列化攔截器進(jìn)行脫敏,這種類似方案,比較知名的實(shí)現(xiàn)如唯品會(huì)脫敏方案。

該方案有明顯的缺點(diǎn),即需對分散在代碼中的所有l(wèi)og打印進(jìn)行改造,工作量大,并且容易遺漏。

方案二

該方案是將脫敏邏輯,與業(yè)務(wù)代碼剝離開,在日志框架層面進(jìn)行實(shí)現(xiàn)。以logback為例,可以從以下兩個(gè)擴(kuò)展點(diǎn)進(jìn)行實(shí)現(xiàn)。

自定義PatternLayout

在使用logback時(shí),一般會(huì)自定義日志輸出內(nèi)容格式,使用PatternLayout來格式化,類似如下

<!-- CONSOLE Appender -->
 ? ?<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
 ? ? ? ?<layout class="ch.qos.logback.classic.PatternLayout">
 ? ? ? ? ? ?<pattern>
 ? ? ? ? ? ? ?  d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
 ? ? ? ? ? ?</pattern>
 ? ? ? ?</layout>
 ? ?</appender>

直接自定義PatternLayout對msg進(jìn)行脫敏

public class DataMaskingPatternLayout extends PatternLayout {
 ? ?@Override
 ? ?public String doLayout(ILoggingEvent event) {
 ? ? ? ?String msg = super.doLayout(event);
 ? ?    //字符串脫敏處理
 ? ?    return doMask(msg);
 ?  }
}

存在的問題

  • 脫敏處理的對象是字符串,脫敏內(nèi)容的識別需要使用多種正則匹配;
  • 無論是否有入?yún)?、是否有敏感字段,所有日志?nèi)容都需要執(zhí)行多種正則匹配;

可以看到,自定義PatternLayout的性能相對來說是比較低的,所以實(shí)際項(xiàng)目上并不推薦該方案。

自定義Converter(推薦)

自定義PatternLayout是對格式化后的字符串進(jìn)行脫敏,可拓展性較差。實(shí)際項(xiàng)目中,為了識別不同的日志信息后脫敏,更多的是自定義日志格式轉(zhuǎn)換器Converter來實(shí)現(xiàn)脫敏。簡單看下如何使用

//ClassicConverter是一個(gè)抽象類,是Converter的子類
public class DataMaskingConverter extends ClassicConverter {
 ? ?@Override
 ? ?public String convert(ILoggingEvent event) {
 ? ? ? ?if (event == null) {
 ? ? ? ? ? ?return null;
 ? ? ?  }
 ? ?    //log參數(shù)脫敏
 ? ?    Object[] maskArgs = argsToMask(event.getArgumentArray());
 ? ?    //參數(shù)脫敏后參與格式化
 ? ?    String msg = MessageFormatter.arrayFormat(event.getMessage(),maskArgs).getMessage();
 ? ? ? ?return msg;
 ?  }
 ? ?@Override
 ? ?public Object[] argsToMask(Object[] argumentArray) {
 ? ? ? ?if (argumentArray == null) {
 ? ? ? ? ? ?return null;
 ? ? ?  }
 ? ? ? ?Object[] res = new Object[argumentArray.length];
 ? ? ? ?int i = 0;
 ? ? ? ?for (Object arg : argumentArray) {
 ? ? ? ? ? ?if (arg == null || arg instanceof Throwable) {
 ? ? ? ? ? ? ? ?res[i] = arg;
 ? ? ? ? ? ? ? ?continue;
 ? ? ? ? ?  }
 ? ? ? ?    if (ObjectUtil.isBasicType(arg)) {
 ? ? ? ? ? ?    if(arg instanceof String && JsonUtil.isJson(arg)){
 ? ? ? ? ? ? ? ? ?//json字符串
 ? ? ? ? ? ? ?    res[i] = DataMask.maskJsonStr(arg);
 ? ? ? ? ? ? ?  } else {
 ? ? ? ? ? ? ? ? ?//其他基礎(chǔ)數(shù)據(jù)類型
 ? ? ? ? ? ? ? ? ?res[i] = arg;
 ? ? ? ? ? ? ?  }
 ? ? ? ? ? ?    continue;
 ? ? ? ? ?  } 
 ? ? ? ?    if {
 ? ? ? ? ? ?    //其他對象
 ? ? ? ? ? ? ? ?res[i] = DataMask.toJSONString(arg);
 ? ? ? ? ?  }
 ? ? ? ? ? ?i++;
 ? ? ?  }
 ? ? ? ?return res;
 ?  }
}

在logback配置文件中,新增配置

<configuration>
    <!-- conversionWord="msg",其中msg就是對應(yīng)pattern標(biāo)簽中的msg -->
 ? ?<conversionRule conversionWord="msg" ?converterClass="cn.cc.DataMaskingConverter"/>
</configuration>

可以看到,自定義Converter可以對入?yún)⒌念愋蛠磉x擇不同的脫敏操作,相對PatternLayout來說,減少大量正則匹配,大幅提高性能。此時(shí)log.info("內(nèi)容:{}",JSON.toJsonString(dto)) 需要改寫成log.info("內(nèi)容:{}",dto)。

但自定義Converter也存在一些問題

  • 對于入?yún)⑹亲址娜罩荆鏻og.info("xx",JSON.toJsonString(dto))、log.info("xx",dto.toString()),如果字符串中包含敏感字段,想要識別,只能通過多種正則進(jìn)行匹配;
  • 若直接使用log.info()方法沒有參數(shù),直接打印字符串的話,如果字符串中包含敏感字段,且需要進(jìn)行脫敏處理,則自定義Converter也將退化成類似前面自定義PatternLayout,只能使用正則匹配的方法實(shí)現(xiàn)脫敏。

針對自定義Converter存在的問題,在實(shí)際項(xiàng)目中可以發(fā)現(xiàn),如果想要單獨(dú)依賴自定義Converter完全解決日志脫敏的問題,是非常困難的,因此有以下建議

  • log的方法使用時(shí),盡量帶上參數(shù);
  • 盡量避免入?yún)镾tring;

到此這篇關(guān)于Java數(shù)據(jù)脫敏實(shí)現(xiàn)的方法總結(jié)的文章就介紹到這了,更多相關(guān)Java數(shù)據(jù)脫敏內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • JAVA中Comparable接口和自定義比較器示例講解

    JAVA中Comparable接口和自定義比較器示例講解

    這篇文章主要給大家介紹了關(guān)于JAVA中Comparable接口和自定義比較器的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java多線程(單例模式,堵塞隊(duì)列,定時(shí)器)詳解

    Java多線程(單例模式,堵塞隊(duì)列,定時(shí)器)詳解

    這篇文章主要介紹了java多線程的(單例模式,堵塞隊(duì)列,定時(shí)器),具有一定參考價(jià)值,加深多線程編程的理解還是很有幫助的,需要的朋友可以參考下
    2021-08-08
  • Java純代碼實(shí)現(xiàn)導(dǎo)出pdf

    Java純代碼實(shí)現(xiàn)導(dǎo)出pdf

    在項(xiàng)目開發(fā)中,產(chǎn)品的需求越來越奇葩啦,開始文件下載都是下載為excel的,做著做著需求竟然變了,要求能導(dǎo)出pdf,所以本文就來用Java實(shí)現(xiàn)導(dǎo)出pdf功能吧
    2023-12-12
  • Java中的instanceof關(guān)鍵字在Android中的用法實(shí)例詳解

    Java中的instanceof關(guān)鍵字在Android中的用法實(shí)例詳解

    instanceof是Java的一個(gè)二元操作符,和==,>,<是同一類東西。接下來通過本文給大家介紹Java中的instanceof關(guān)鍵字在Android中的用法,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-07-07
  • kotlin和Java的相互調(diào)用示例詳解

    kotlin和Java的相互調(diào)用示例詳解

    Kotlin 的設(shè)計(jì)過程中就考慮到了與 Java 的互操作性。在 Kotlin 中可以直接調(diào)用既有的 Java 代碼, 反過來在 Java 中也可以很流暢地使用 Kotlin 代碼,下面這篇文章主要給大家介紹了關(guān)于kotlin和Java的相互調(diào)用的相關(guān)資料,需要的朋友可以參考下。
    2018-02-02
  • SpringBoot項(xiàng)目如何將Bean注入到普通類中

    SpringBoot項(xiàng)目如何將Bean注入到普通類中

    這篇文章主要介紹了SpringBoot項(xiàng)目如何將Bean注入到普通類中,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java注解的Retention和RetentionPolicy實(shí)例分析

    Java注解的Retention和RetentionPolicy實(shí)例分析

    這篇文章主要介紹了Java注解的Retention和RetentionPolicy,結(jié)合實(shí)例形式分析了Java注解Retention和RetentionPolicy的基本功能及使用方法,需要的朋友可以參考下
    2019-09-09
  • java?Long類型轉(zhuǎn)為json后數(shù)據(jù)損失精度的處理方式

    java?Long類型轉(zhuǎn)為json后數(shù)據(jù)損失精度的處理方式

    這篇文章主要介紹了java?Long類型轉(zhuǎn)為json后數(shù)據(jù)損失精度的處理方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 如何應(yīng)對spring框架的HTTP ERROR 400 Bad Request錯(cuò)誤返回問題

    如何應(yīng)對spring框架的HTTP ERROR 400 Bad Request錯(cuò)

    這篇文章主要介紹了如何應(yīng)對spring框架的HTTP ERROR 400 Bad Request錯(cuò)誤返回問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Springboot整合mqtt服務(wù)的示例代碼

    Springboot整合mqtt服務(wù)的示例代碼

    MQTT是一個(gè)基于客戶端-服務(wù)器的消息發(fā)布/訂閱傳輸協(xié)議。MQTT協(xié)議是輕量、簡單、開放和易于實(shí)現(xiàn)的,這些特點(diǎn)使它適用范圍非常廣泛。本文為大家分享了Springboot整合mqtt服務(wù)的示例代碼,需要的可以參考一下
    2022-03-03

最新評論

出国| 蓬溪县| 抚宁县| 桂林市| 和林格尔县| 昆山市| 周宁县| 苍南县| 康保县| 准格尔旗| 宁安市| 阿拉善右旗| 连州市| 临澧县| 宜宾市| 华容县| 庆安县| 视频| 谢通门县| 宜章县| 松滋市| 兰考县| 丹棱县| 安图县| 罗江县| 和林格尔县| 怀宁县| 滦南县| 利津县| 独山县| 彰武县| 富顺县| 伊宁县| 尚志市| 德安县| 乌苏市| 吉林省| 定安县| 闻喜县| 通化市| 铁力市|