1. 什么是數(shù)據(jù)脫敏
1.1 數(shù)據(jù)脫敏的定義
數(shù)據(jù)脫敏百度百科中是這樣定義的: 數(shù)據(jù)脫敏,指對(duì)某些敏感信息通過(guò)脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。
這樣就可以在開(kāi)發(fā)、測(cè)試和其它非生產(chǎn)環(huán)境以及外包環(huán)境中安全地使用脫敏后的真實(shí)數(shù)據(jù)集。在涉及客戶安全數(shù)據(jù)或者一些商業(yè)性敏感數(shù)據(jù)的情況下,在不違反系統(tǒng)規(guī)則條件下,對(duì)真實(shí)數(shù)據(jù)進(jìn)行改造并提供測(cè)試使用,如身份證號(hào)、手機(jī)號(hào)、卡號(hào)、客戶號(hào)等個(gè)人信息都需要進(jìn)行數(shù)據(jù)脫敏。是數(shù)據(jù)庫(kù)安全技術(shù)之一。
總的來(lái)說(shuō),數(shù)據(jù)脫敏是指對(duì)某些敏感信息通過(guò)脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。
在數(shù)據(jù)脫敏過(guò)程中,通常會(huì)采用不同的算法和技術(shù),以根據(jù)不同的需求和場(chǎng)景對(duì)數(shù)據(jù)進(jìn)行處理。
例如,對(duì)于身份證號(hào)碼,可以使用掩碼算法(masking)將前幾位數(shù)字保留,其他位用 “X” 或 "*" 代替;對(duì)于姓名,可以使用偽造(pseudonymization)算法,將真實(shí)姓名替換成隨機(jī)生成的假名。
1.2 常用脫敏規(guī)則
替換、重排、加密、截?cái)?、掩碼
2. Hutool 工具介紹
2.1 引入 Maven 配置
在項(xiàng)目的 pom.xml 的 dependencies 中加入以下內(nèi)容,這里以 5.8.16 版本為例。
注意:Hutool 5.x 支持 JDK8+, 如果你的項(xiàng)目使用 JDK7,請(qǐng)使用 Hutool 4.x 版本。本文使用的數(shù)據(jù)脫敏工具類只有在 5.6 + 版本以上才提供。
2.2 Hutool 包含的組件
一個(gè) Java 基礎(chǔ)工具類,對(duì)文件、流、加密解密、轉(zhuǎn)碼、正則、線程、XML 等 JDK 方法進(jìn)行封裝,組成各種 Util 工具類,同時(shí)提供以下組件:
模塊 | 介紹 |
---|---|
hutool-aop | JDK 動(dòng)態(tài)代理封裝,提供非 IOC 下的切面支持 |
hutool-bloomFilter | 布隆過(guò)濾,提供一些 Hash 算法的布隆過(guò)濾 |
hutool-cache | 簡(jiǎn)單緩存實(shí)現(xiàn) |
hutool-core | 核心,包括 Bean 操作、日期、各種 Util 等 |
hutool-cron | 定時(shí)任務(wù)模塊,提供類 Crontab 表達(dá)式的定時(shí)任務(wù) |
hutool-crypto | 加密解密模塊,提供對(duì)稱、非對(duì)稱和摘要算法封裝 |
hutool-db | JDBC 封裝后的數(shù)據(jù)操作,基于 ActiveRecord 思想 |
hutool-dfa | 基于 DFA 模型的多關(guān)鍵字查找 |
hutool-extra | 擴(kuò)展模塊,對(duì)第三方封裝(模板引擎、郵件、Servlet、二維碼、Emoji、FTP、分詞等) |
hutool-http | 基于 HttpUrlConnection 的 Http 客戶端封裝 |
hutool-log | 自動(dòng)識(shí)別日志實(shí)現(xiàn)的日志門(mén)面 |
hutool-script | 腳本執(zhí)行封裝,例如 Javascript |
hutool-setting | 功能更強(qiáng)大的 Setting 配置文件和 Properties 封裝 |
hutool-system | 系統(tǒng)參數(shù)調(diào)用封裝(JVM 信息等) |
hutool-json | JSON 實(shí)現(xiàn) |
hutool-captcha | 圖片驗(yàn)證碼實(shí)現(xiàn) |
hutool-poi | 針對(duì) POI 中 Excel 和 Word 的封裝 |
hutool-socket | 基于 Java 的 NIO 和 AIO 的 Socket 封裝 |
hutool-jwt | JSON Web Token (JWT) 封裝實(shí)現(xiàn) |
可以根據(jù)需求對(duì)每個(gè)模塊單獨(dú)引入,也可以通過(guò)引入hutool-all方式引入所有模塊,本文所使用的數(shù)據(jù)脫敏工具就是在 hutool.core 模塊。
2.3 Hutool 支持的脫敏數(shù)據(jù)類型
現(xiàn)階段最新版本的 Hutool 支持的脫敏數(shù)據(jù)類型如下,基本覆蓋了常見(jiàn)的敏感信息。
1.用戶 id
2.中文姓名
3.身份證號(hào)
4.座機(jī)號(hào)
5.手機(jī)號(hào)
6.地址
7.電子郵件
8.密碼
9.中國(guó)大陸車(chē)牌,包含普通車(chē)輛、新能源車(chē)輛
10.銀行卡
3. Hutool 數(shù)據(jù)脫敏實(shí)操
3.1 使用 Hutool 工具類一行代碼實(shí)現(xiàn)脫敏
Hutool 提供的脫敏方法如下圖所示:
??
注意:Hutool 脫敏是通過(guò) * 來(lái)代替敏感信息的,具體實(shí)現(xiàn)是在 StrUtil.hide 方法中,如果我們想要自定義隱藏符號(hào),則可以把 Hutool 的源碼拷出來(lái),重新實(shí)現(xiàn)即可。 這里以手機(jī)號(hào)、銀行卡號(hào)、身份證號(hào)、密碼信息的脫敏為例,下面是對(duì)應(yīng)的測(cè)試代碼。
importcn.hutool.core.util.DesensitizedUtil; importorg.junit.Test; importorg.springframework.boot.test.context.SpringBootTest; /** * * @description: Hutool實(shí)現(xiàn)數(shù)據(jù)脫敏 */ @SpringBootTest publicclassHuToolDesensitizationTest{ @Test publicvoidtestPhoneDesensitization(){ String phone="13723231234"; System.out.println(DesensitizedUtil.mobilePhone(phone));//輸出:137****1234 } @Test publicvoidtestBankCardDesensitization(){ String bankCard="6217000130008255666"; System.out.println(DesensitizedUtil.bankCard(bankCard));//輸出:6217 **** **** *** 5666 } @Test publicvoidtestIdCardNumDesensitization(){ String idCardNum="411021199901102321"; //只顯示前4位和后2位 System.out.println(DesensitizedUtil.idCardNum(idCardNum,4,2));//輸出:4110************21 } @Test publicvoidtestPasswordDesensitization(){ String password="www.jd.com_35711"; System.out.println(DesensitizedUtil.password(password));//輸出:**************** } }以上就是使用 Hutool 封裝好的工具類實(shí)現(xiàn)數(shù)據(jù)脫敏。
3.2 配合 JackSon 通過(guò)注解方式實(shí)現(xiàn)脫敏
現(xiàn)在有了數(shù)據(jù)脫敏工具類,如果前端需要顯示數(shù)據(jù)數(shù)據(jù)的地方比較多,我們不可能在每個(gè)地方都調(diào)用一個(gè)工具類,這樣就顯得代碼太冗余了,那我們?nèi)绾瓮ㄟ^(guò)注解的方式優(yōu)雅的完成數(shù)據(jù)脫敏呢? 如果項(xiàng)目是基于 springboot 的 web 項(xiàng)目,則可以利用 springboot 自帶的 jackson 自定義序列化實(shí)現(xiàn)。它的實(shí)現(xiàn)原來(lái)其實(shí)就是在 json 進(jìn)行序列化渲染給前端時(shí),進(jìn)行脫敏。
第一步:脫敏策略的枚舉。
/** * @author * @description:脫敏策略枚舉 */ publicenumDesensitizationTypeEnum{ //自定義 MY_RULE, //用戶id USER_ID, //中文名 CHINESE_NAME, //身份證號(hào) ID_CARD, //座機(jī)號(hào) FIXED_PHONE, //手機(jī)號(hào) MOBILE_PHONE, //地址 ADDRESS, //電子郵件 EMAIL, //密碼 PASSWORD, //中國(guó)大陸車(chē)牌,包含普通車(chē)輛、新能源車(chē)輛 CAR_LICENSE, //銀行卡 BANK_CARD }上面表示支持的脫敏類型。
第二步:定義一個(gè)用于脫敏的 Desensitization 注解。
@Retention (RetentionPolicy.RUNTIME):運(yùn)行時(shí)生效。
@Target (ElementType.FIELD):可用在字段上。
@JacksonAnnotationsInside:此注解可以點(diǎn)進(jìn)去看一下是一個(gè)元注解,主要是用戶打包其他注解一起使用。
@JsonSerialize:上面說(shuō)到過(guò),該注解的作用就是可自定義序列化,可以用在注解上,方法上,字段上,類上,運(yùn)行時(shí)生效等等,根據(jù)提供的序列化類里面的重寫(xiě)方法實(shí)現(xiàn)自定義序列化。
/** * @author */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonSerialize(using =DesensitizationSerialize.class) public@interface Desensitization{ /** * 脫敏數(shù)據(jù)類型,在MY_RULE的時(shí)候,startInclude和endExclude生效 */ DesensitizationTypeEnumtype()defaultDesensitizationTypeEnum.MY_RULE; /** * 脫敏開(kāi)始位置(包含) */ intstartInclude()default0; /** * 脫敏結(jié)束位置(不包含) */ intendExclude()default0; }注:只有使用了自定義的脫敏枚舉 MY_RULE 的時(shí)候,開(kāi)始位置和結(jié)束位置才生效。
第三步:創(chuàng)建自定的序列化類 這一步是我們實(shí)現(xiàn)數(shù)據(jù)脫敏的關(guān)鍵。自定義序列化類繼承 JsonSerializer,實(shí)現(xiàn) ContextualSerializer 接口,并重寫(xiě)兩個(gè)方法。
/** * @author * @description: 自定義序列化類 */ @AllArgsConstructor @NoArgsConstructor publicclassDesensitizationSerializeextendsJsonSerializer經(jīng)過(guò)上述三步,已經(jīng)完成了通過(guò)注解實(shí)現(xiàn)數(shù)據(jù)脫敏了,下面我們來(lái)測(cè)試一下。 首先定義一個(gè)要測(cè)試的 pojo,對(duì)應(yīng)的字段加入要脫敏的策略。implementsContextualSerializer{ privateDesensitizationTypeEnum type; privateInteger startInclude; privateInteger endExclude; @Override publicvoidserialize(String str,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throwsIOException{ switch(type){ // 自定義類型脫敏 case MY_RULE: jsonGenerator.writeString(CharSequenceUtil.hide(str, startInclude, endExclude)); break; // userId脫敏 case USER_ID: jsonGenerator.writeString(String.valueOf(DesensitizedUtil.userId())); break; // 中文姓名脫敏 case CHINESE_NAME: jsonGenerator.writeString(DesensitizedUtil.chineseName(String.valueOf(str))); break; // 身份證脫敏 case ID_CARD: jsonGenerator.writeString(DesensitizedUtil.idCardNum(String.valueOf(str),1,2)); break; // 固定電話脫敏 case FIXED_PHONE: jsonGenerator.writeString(DesensitizedUtil.fixedPhone(String.valueOf(str))); break; // 手機(jī)號(hào)脫敏 case MOBILE_PHONE: jsonGenerator.writeString(DesensitizedUtil.mobilePhone(String.valueOf(str))); break; // 地址脫敏 case ADDRESS: jsonGenerator.writeString(DesensitizedUtil.address(String.valueOf(str),8)); break; // 郵箱脫敏 case EMAIL: jsonGenerator.writeString(DesensitizedUtil.email(String.valueOf(str))); break; // 密碼脫敏 case PASSWORD: jsonGenerator.writeString(DesensitizedUtil.password(String.valueOf(str))); break; // 中國(guó)車(chē)牌脫敏 case CAR_LICENSE: jsonGenerator.writeString(DesensitizedUtil.carLicense(String.valueOf(str))); break; // 銀行卡脫敏 case BANK_CARD: jsonGenerator.writeString(DesensitizedUtil.bankCard(String.valueOf(str))); break; default: } } @Override publicJsonSerializer> createContextual(SerializerProvider serializerProvider,BeanProperty beanProperty)throwsJsonMappingException{ if(beanProperty !=null){ // 判斷數(shù)據(jù)類型是否為String類型 if(Objects.equals(beanProperty.getType().getRawClass(),String.class)){ // 獲取定義的注解 Desensitization desensitization = beanProperty.getAnnotation(Desensitization.class); // 為null if(desensitization ==null){ desensitization = beanProperty.getContextAnnotation(Desensitization.class); } // 不為null if(desensitization !=null){ // 創(chuàng)建定義的序列化類的實(shí)例并且返回,入?yún)樽⒔舛x的type,開(kāi)始位置,結(jié)束位置。 returnnewDesensitizationSerialize(desensitization.type(), desensitization.startInclude(), desensitization.endExclude()); } } return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty); } return serializerProvider.findNullValueSerializer(null); } }
/** * * @description: */ @Data @NoArgsConstructor @AllArgsConstructor publicclassTestPojo{ privateString userName; @Desensitization(type =DesensitizationTypeEnum.MOBILE_PHONE) privateString phone; @Desensitization(type =DesensitizationTypeEnum.PASSWORD) privateString password; @Desensitization(type =DesensitizationTypeEnum.MY_RULE, startInclude =0, endExclude =2) privateString address; }
接下來(lái)寫(xiě)一個(gè)測(cè)試的 controller
@RestController publicclassTestController{ @RequestMapping("/test") publicTestPojotestDesensitization(){ TestPojo testPojo =newTestPojo(); testPojo.setUserName("我是用戶名"); testPojo.setAddress("地球中國(guó)-北京市通州區(qū)京東總部2號(hào)樓"); testPojo.setPhone("13782946666"); testPojo.setPassword("sunyangwei123123123."); System.out.println(testPojo); return testPojo; } }??
可以看到我們成功實(shí)現(xiàn)了數(shù)據(jù)脫敏。
4. 其他常見(jiàn)的數(shù)據(jù)脫敏工具推薦
除了本文介紹的 Hutool 工具之外,還有一些其他的數(shù)據(jù)脫敏工具,常見(jiàn)脫敏方法或工具如下所示:
4.1 Apache ShardingSphere
Apache ShardingSphere 下面存在一個(gè)數(shù)據(jù)脫敏模塊,此模塊集成的常用的數(shù)據(jù)脫敏的功能。其基本原理是對(duì)用戶輸入的 SQL 進(jìn)行解析攔截,并依靠用戶的脫敏配置進(jìn)行 SQL 的改寫(xiě),從而實(shí)現(xiàn)對(duì)原文字段的加密及加密字段的解密。最終實(shí)現(xiàn)對(duì)用戶無(wú)感的加解密存儲(chǔ)、查詢。
4.2 FastJSON
平時(shí)開(kāi)發(fā) Web 項(xiàng)目的時(shí)候,除了默認(rèn)的 Spring 自帶的序列化工具,F(xiàn)astJson 也是一個(gè)很常用的 Spring web Restful 接口序列化的工具。 FastJSON 實(shí)現(xiàn)數(shù)據(jù)脫敏的方式主要有兩種:
基于注解 @JSONField 實(shí)現(xiàn):需要自定義一個(gè)用于脫敏的序列化的類,然后在需要脫敏的字段上通過(guò) @JSONField 中的 serializeUsing 指定為我們自定義的序列化類型即可。
基于序列化過(guò)濾器:需要實(shí)現(xiàn) ValueFilter 接口,重寫(xiě) process 方法完成自定義脫敏,然后在 JSON 轉(zhuǎn)換時(shí)使用自定義的轉(zhuǎn)換策略。具體實(shí)現(xiàn)可參考這篇文章:https://juejin.cn/post/7067916686141161479
4.3 Mybatis-mate
mybatisplus 也提供了數(shù)據(jù)脫敏模塊,mybatis-mate,不過(guò)在使用之前需要配置授權(quán)碼。 配置內(nèi)容如下所示:
# Mybatis Mate 配置 mybatis-mate: cert: grant: jxftsdfggggx license: GKXP9r4MCJhGID/DTGigcBcLmZjb1YZGjE4GXaAoxbtGsPC20sxpEtiUr2F7Nb1ANTUekvF6Syo6DzraA4M4oacwoLVTglzfvaEfadfsd232485eLJK1QsskrSJmreMnEaNh9lsV7Lpbxy9JeGCeM0HPEbRvq8Y+8dUt5bQYLklsa3ZIBexir+4XykZY15uqn1pYIp4pEK0+aINTa57xjJNoWuBIqm7BdFIb4l1TAcPYMTsMXhF5hfMmKD2h391HxWTshJ6jbt4YqdKD167AgeoM+B+DE1jxlLjcpskY+kFs9piOS7RCcmKBBUOgX2BD/JxhR2gQ==
5. 總結(jié)
本文主要介紹了數(shù)據(jù)脫敏的相關(guān)內(nèi)容,首先介紹了數(shù)據(jù)脫敏的概念,在此基礎(chǔ)上介紹了常用的數(shù)據(jù)脫敏規(guī)則;隨后介紹了本文的重點(diǎn) Hutool 工具及其使用方法,在此基礎(chǔ)上進(jìn)行了實(shí)操,分別演示了使用 DesensitizedUtil 工具類、配合 Jackson 通過(guò)注解的方式完成數(shù)據(jù)脫敏.
審核編輯:劉清
-
SQL
+關(guān)注
關(guān)注
1文章
753瀏覽量
44032 -
FTP
+關(guān)注
關(guān)注
0文章
106瀏覽量
40568 -
JVM
+關(guān)注
關(guān)注
0文章
157瀏覽量
12197 -
過(guò)濾器
+關(guān)注
關(guān)注
1文章
427瀏覽量
19519 -
JSON
+關(guān)注
關(guān)注
0文章
116瀏覽量
6929
原文標(biāo)題:Hutool:一行代碼搞定數(shù)據(jù)脫敏
文章出處:【微信號(hào):OSC開(kāi)源社區(qū),微信公眾號(hào):OSC開(kāi)源社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論