RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何實現(xiàn)SpringBoot項目中的隱私數(shù)據(jù)脫敏呢

jf_ro2CN3Fa ? 來源:csdn ? 2023-01-08 10:25 ? 次閱讀

這兩天在整改等保測出的問題,里面有一個“用戶信息泄露”的風(fēng)險項(就是后臺系統(tǒng)里用戶的一些隱私數(shù)據(jù)直接明文顯示了),其實指的就是要做數(shù)據(jù)脫敏。

數(shù)據(jù)脫敏:把系統(tǒng)里的一些敏感數(shù)據(jù)進行加密處理后再返回,達到保護隱私作用,實現(xiàn)效果圖如下:

603865d0-8ef9-11ed-bfe3-dac502259ad0.png

其實要實現(xiàn)上面的效果,可能最先想到的方法是直接改每個controller接口,在返回數(shù)據(jù)前做一次加密處理,當(dāng)然這個方法肯定是非常撈的。這里推薦用注解來實現(xiàn),即高效又優(yōu)雅,省時省力,支持?jǐn)U展。

其實解決方案大體上分兩種:

在拿到數(shù)據(jù)時就已經(jīng)脫敏了(如在 mysql 查詢時用 insert 函數(shù)進行隱藏)

拿到數(shù)據(jù)后在序列化的時候再進行脫敏(如用 fastjson、jackson)

這里我所選用的方案是第二種,即在接口返回數(shù)據(jù)前,在序列化的時候?qū)γ舾凶侄沃颠M行處理,并且選用 jackson 的序列化來實現(xiàn)(推薦)

1. 創(chuàng)建隱私數(shù)據(jù)類型枚舉:PrivacyTypeEnum

importlombok.Getter;

/**
*隱私數(shù)據(jù)類型枚舉
*/
@Getter
publicenumPrivacyTypeEnum{

/**自定義(此項需設(shè)置脫敏的范圍)*/
CUSTOMER,

/**姓名*/
NAME,

/**身份證號*/
ID_CARD,

/**手機號*/
PHONE,

/**郵箱*/
EMAIL,
}

基于 Spring Boot + MyBatis Plus + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

2. 創(chuàng)建自定義隱私注解:PrivacyEncrypt

importcom.fasterxml.jackson.annotation.JacksonAnnotationsInside;
importcom.fasterxml.jackson.databind.annotation.JsonSerialize;

importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;

/**
*自定義數(shù)據(jù)脫敏注解
*/
@Target(ElementType.FIELD)//作用在字段上
@Retention(RetentionPolicy.RUNTIME)//class文件中保留,運行時也保留,能通過反射讀取到
@JacksonAnnotationsInside//表示自定義自己的注解PrivacyEncrypt
@JsonSerialize(using=PrivacySerializer.class)//該注解使用序列化的方式
public@interfacePrivacyEncrypt{

/**
*脫敏數(shù)據(jù)類型(沒給默認(rèn)值,所以使用時必須指定type)
*/
PrivacyTypeEnumtype();

/**
*前置不需要打碼的長度
*/
intprefixNoMaskLen()default1;

/**
*后置不需要打碼的長度
*/
intsuffixNoMaskLen()default1;

/**
*用什么打碼
*/
Stringsymbol()default"*";
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現(xiàn)的后臺管理系統(tǒng) + 用戶小程序,支持 RBAC 動態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

3. 創(chuàng)建自定義序列化器:PrivacySerializer

importcom.fasterxml.jackson.core.JsonGenerator;
importcom.fasterxml.jackson.databind.BeanProperty;
importcom.fasterxml.jackson.databind.JsonMappingException;
importcom.fasterxml.jackson.databind.JsonSerializer;
importcom.fasterxml.jackson.databind.SerializerProvider;
importcom.fasterxml.jackson.databind.ser.ContextualSerializer;
importcom.zk.common.core.domain.enumerate.PrivacyTypeEnum;
importcom.zk.common.core.utils.PrivacyUtil;
importjava.io.IOException;
importjava.util.Objects;
importlombok.AllArgsConstructor;
importlombok.NoArgsConstructor;
importorg.apache.commons.lang3.StringUtils;

@NoArgsConstructor
@AllArgsConstructor
publicclassPrivacySerializerextendsJsonSerializerimplementsContextualSerializer{

//脫敏類型
privatePrivacyTypeEnumprivacyTypeEnum;
//前幾位不脫敏
privateIntegerprefixNoMaskLen;
//最后幾位不脫敏
privateIntegersuffixNoMaskLen;
//用什么打碼
privateStringsymbol;

@Override
publicvoidserialize(finalStringorigin,finalJsonGeneratorjsonGenerator,
finalSerializerProviderserializerProvider)throwsIOException{
if(StringUtils.isNotBlank(origin)&&null!=privacyTypeEnum){
switch(privacyTypeEnum){
caseCUSTOMER:
jsonGenerator.writeString(PrivacyUtil.desValue(origin,prefixNoMaskLen,suffixNoMaskLen,symbol));
break;
caseNAME:
jsonGenerator.writeString(PrivacyUtil.hideChineseName(origin));
break;
caseID_CARD:
jsonGenerator.writeString(PrivacyUtil.hideIDCard(origin));
break;
casePHONE:
jsonGenerator.writeString(PrivacyUtil.hidePhone(origin));
break;
caseEMAIL:
jsonGenerator.writeString(PrivacyUtil.hideEmail(origin));
break;
default:
thrownewIllegalArgumentException("unknownprivacytypeenum"+privacyTypeEnum);
}
}
}

@Override
publicJsonSerializercreateContextual(finalSerializerProviderserializerProvider,
finalBeanPropertybeanProperty)throwsJsonMappingException{
if(beanProperty!=null){
if(Objects.equals(beanProperty.getType().getRawClass(),String.class)){
PrivacyEncryptprivacyEncrypt=beanProperty.getAnnotation(PrivacyEncrypt.class);
if(privacyEncrypt==null){
privacyEncrypt=beanProperty.getContextAnnotation(PrivacyEncrypt.class);
}
if(privacyEncrypt!=null){
returnnewPrivacySerializer(privacyEncrypt.type(),privacyEncrypt.prefixNoMaskLen(),
privacyEncrypt.suffixNoMaskLen(),privacyEncrypt.symbol());
}
}
returnserializerProvider.findValueSerializer(beanProperty.getType(),beanProperty);
}
returnserializerProvider.findNullValueSerializer(null);
}
}

這里是具體的實現(xiàn)過程,因為要脫敏的數(shù)據(jù)都是 String 類型的,所以繼承 JsonSerializer 時的類型填 String

重寫的 serialize 方法是實現(xiàn)脫敏的核心,根據(jù)類型 type 的不同去設(shè)置序列化后的值

重寫的 createContextual 方法就是去讀取我們自定義的 PrivacyEncrypt 注解,打造一個上下文的環(huán)境。

4. 隱私數(shù)據(jù)隱藏工具類:PrivacyUtil

publicclassPrivacyUtil{

/**
*隱藏手機號中間四位
*/
publicstaticStringhidePhone(Stringphone){
returnphone.replaceAll("(\d{3})\d{4}(\d{4})","$1****$2");
}

/**
*隱藏郵箱
*/
publicstaticStringhideEmail(Stringemail){
returnemail.replaceAll("(\w?)(\w+)(\w)(@\w+\.[a-z]+(\.[a-z]+)?)","$1****$3$4");
}

/**
*隱藏身份證
*/
publicstaticStringhideIDCard(StringidCard){
returnidCard.replaceAll("(\d{4})\d{10}(\w{4})","$1*****$2");
}

/**
*【中文姓名】只顯示第一個漢字,其他隱藏為星號,比如:任**
*/
publicstaticStringhideChineseName(StringchineseName){
if(chineseName==null){
returnnull;
}
returndesValue(chineseName,1,0,"*");
}

///**
//*【身份證號】顯示前4位,后2位
//*/
//publicstaticStringhideIdCard(StringidCard){
//returndesValue(idCard,4,2,"*");
//}

///**
//*【手機號碼】前三位,后四位,其他隱藏。
//*/
//publicstaticStringhidePhone(Stringphone){
//returndesValue(phone,3,4,"*");
//}

/**
*對字符串進行脫敏操作
*@paramorigin原始字符串
*@paramprefixNoMaskLen左側(cè)需要保留幾位明文字段
*@paramsuffixNoMaskLen右側(cè)需要保留幾位明文字段
*@parammaskStr用于遮罩的字符串,如'*'
*@return脫敏后結(jié)果
*/
publicstaticStringdesValue(Stringorigin,intprefixNoMaskLen,intsuffixNoMaskLen,StringmaskStr){
if(origin==null){
returnnull;
}
StringBuildersb=newStringBuilder();
for(inti=0,n=origin.length();i(n-suffixNoMaskLen-1)){
sb.append(origin.charAt(i));
continue;
}
sb.append(maskStr);
}
returnsb.toString();
}

publicstaticvoidmain(String[]args){
System.out.println(hideChineseName("張三三"));
}
}

這個工具類其實可以自己定,根據(jù)自己的業(yè)務(wù)去擴展,提一點:

在自定義注解 PrivacyEncrypt 里,只有 type 的值為 PrivacyTypeEnum.CUSTOMER(自定義)時,才需要指定脫敏范圍,即 prefixNoMaskLen 和 suffixNoMaskLen 的值,像郵箱、手機號這種隱藏格式都采用固定的

5. 注解使用

直接在需要脫敏的字段上加上注解,指定 type 值即可,如下:

@Data
publicclassPeople{

privateIntegerid;

privateStringname;

privateIntegersex;

privateIntegerage;

@PrivacyEncrypt(type=PrivacyTypeEnum.PHONE)//隱藏手機號
privateStringphone;

@PrivacyEncrypt(type=PrivacyTypeEnum.EMAIL)//隱藏郵箱
privateStringemail;

privateStringsign;
}

到這里,脫敏工作就已經(jīng)結(jié)束了,全局使用這一個注解即可,一勞永逸,測試效果圖如下:

604f1096-8ef9-11ed-bfe3-dac502259ad0.png

以上代碼已經(jīng)過測試,并已實際使用,所以可放心使用。







審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • MySQL
    +關(guān)注

    關(guān)注

    1

    文章

    804

    瀏覽量

    26528
  • SpringBoot
    +關(guān)注

    關(guān)注

    0

    文章

    173

    瀏覽量

    177

原文標(biāo)題:僅需一個注解,實現(xiàn) SpringBoot 項目中的隱私數(shù)據(jù)脫敏!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    SpringBoot 如何實現(xiàn)熱部署

    SpringBoot 如何實現(xiàn)熱部署? 1、熱部署的優(yōu)點 開發(fā)周期通常包括編寫代碼、編譯、部署和測試幾個步驟。在一個快速發(fā)展的項目中,這個周期需要盡可能地縮短。熱部署能讓開發(fā)者在代碼更改后立即看到結(jié)果,從而加速開發(fā)和測試過程。
    的頭像 發(fā)表于 09-30 10:16 ?826次閱讀
    <b class='flag-5'>SpringBoot</b> 如何<b class='flag-5'>實現(xiàn)</b>熱部署

    SpringBoot項目數(shù)據(jù)源配置數(shù)據(jù)

    SpringBoot項目數(shù)據(jù)源配置
    發(fā)表于 06-05 09:51

    怎樣去使用springboot

    怎樣去使用springboot?學(xué)習(xí)springboot需要懂得哪些?
    發(fā)表于 10-25 07:13

    SQL/JAVA/mybatisplus數(shù)據(jù)脫敏實現(xiàn)原理

    MYSQL(電話號碼,身份證)數(shù)據(jù)脫敏實現(xiàn)
    的頭像 發(fā)表于 06-14 17:09 ?3885次閱讀

    如何在SpringBoot項目中實現(xiàn)動態(tài)定時任務(wù)

    之前寫過文章記錄怎么在SpringBoot項目中簡單使用定時任務(wù),不過由于要借助cron表達式且都提前定義好放在配置文件里,不能在項目運行中動態(tài)修改任務(wù)執(zhí)行時間,實在不太靈活。
    的頭像 發(fā)表于 09-30 11:16 ?1803次閱讀

    數(shù)據(jù)脫敏技術(shù)定義及實施過程解析

    數(shù)據(jù)脫敏數(shù)據(jù)安全領(lǐng)域落地場景較為成熟的技術(shù)手段,在數(shù)據(jù)深層次、大范圍的共享開放的今天,數(shù)據(jù)脫敏
    的頭像 發(fā)表于 11-16 10:26 ?3528次閱讀

    SpringBoot日志脫敏的方式介紹

    一個項目在書寫了很多打印日志的代碼,但是后面有了脫敏需求,如果我們?nèi)ナ謩痈膭哟a,會花費大量時間。如果引入本組件,完成配置即可輕松完成脫敏。(僅需三步可輕松配置)
    的頭像 發(fā)表于 01-09 10:49 ?2593次閱讀

    SpringBoot實現(xiàn)多線程

    SpringBoot實現(xiàn)多線程
    的頭像 發(fā)表于 01-12 16:59 ?1813次閱讀
    <b class='flag-5'>SpringBoot</b><b class='flag-5'>實現(xiàn)</b>多線程

    如何正確使用SpringBoot項目中緩存Cache

    緩存可以通過將經(jīng)常訪問的數(shù)據(jù)存儲在內(nèi)存中,減少底層數(shù)據(jù)源如數(shù)據(jù)庫的壓力,從而有效提高系統(tǒng)的性能和穩(wěn)定性。我想大家的項目中或多或少都有使用過,我們項目
    的頭像 發(fā)表于 05-11 11:01 ?1205次閱讀
    如何正確使用<b class='flag-5'>SpringBoot</b><b class='flag-5'>項目中</b>緩存Cache

    SpringBoot項目中使用緩存的正確方法

    ? 前言 緩存可以通過將經(jīng)常訪問的數(shù)據(jù)存儲在內(nèi)存中,減少底層數(shù)據(jù)源如數(shù)據(jù)庫的壓力,從而有效提高系統(tǒng)的性能和穩(wěn)定性。我想大家的項目中或多或少都有使用過,我們
    的頭像 發(fā)表于 06-13 10:59 ?3362次閱讀
    <b class='flag-5'>SpringBoot</b><b class='flag-5'>項目中</b>使用緩存的正確方法

    如何實現(xiàn)一個注解進行數(shù)據(jù)脫敏

    、測試 后記 ? 本文主要分享什么是數(shù)據(jù)脫敏,如何優(yōu)雅的在項目中運用一個注解實現(xiàn)數(shù)據(jù)脫敏,為
    的頭像 發(fā)表于 06-14 09:37 ?1010次閱讀
    如何<b class='flag-5'>實現(xiàn)</b>一個注解進行<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>

    Springboot項目的集成以及具體使用及配置

    ? 概念 核心組件 API介紹 Springboot集成 具體業(yè)務(wù)集成 API使用 ? 前言 項目中需要用到工作流引擎來設(shè)計部分業(yè)務(wù)流程,框架選型最終選擇了 Camunda7,關(guān)于 Camunda
    的頭像 發(fā)表于 07-03 11:18 ?1509次閱讀
    <b class='flag-5'>Springboot</b><b class='flag-5'>項目</b>的集成以及具體使用及配置

    什么是數(shù)據(jù)脫敏?常用的脫敏規(guī)則有哪些?

    數(shù)據(jù)脫敏,指對某些敏感信息通過脫敏規(guī)則進行數(shù)據(jù)的變形,實現(xiàn)敏感隱私
    的頭像 發(fā)表于 08-15 10:04 ?2.4w次閱讀
    什么是<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>?常用的<b class='flag-5'>脫敏</b>規(guī)則有哪些<b class='flag-5'>呢</b>?

    SpringBoot采用JsonSerializer和Aop實現(xiàn)可控制的數(shù)據(jù)脫敏

    的確實現(xiàn)數(shù)據(jù)脫敏,但是有個問題現(xiàn)在的脫敏針對的是 只要對該實體類進行了使用返回的接口,中的數(shù)據(jù)都會進行
    的頭像 發(fā)表于 11-06 16:15 ?1639次閱讀
    <b class='flag-5'>SpringBoot</b>采用JsonSerializer和Aop<b class='flag-5'>實現(xiàn)</b>可控制的<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>

    數(shù)據(jù)脫敏的3種常見方案,好用到爆!

    數(shù)據(jù)脫敏插件,目前支持地址脫敏、銀行卡號脫敏、中文姓名脫敏、固話脫敏、身份證號
    的頭像 發(fā)表于 02-25 16:14 ?1788次閱讀
    <b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>脫敏</b>的3種常見方案,好用到爆!
    RM新时代网站-首页