色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何實現SpringBoot項目中的隱私數據脫敏呢

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

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

數據脫敏:把系統里的一些敏感數據進行加密處理后再返回,達到保護隱私作用,實現效果圖如下:

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

其實要實現上面的效果,可能最先想到的方法是直接改每個controller接口,在返回數據前做一次加密處理,當然這個方法肯定是非常撈的。這里推薦用注解來實現,即高效又優雅,省時省力,支持擴展。

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

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

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

這里我所選用的方案是第二種,即在接口返回數據前,在序列化的時候對敏感字段值進行處理,并且選用 jackson 的序列化來實現(推薦)

1. 創建隱私數據類型枚舉:PrivacyTypeEnum

importlombok.Getter;

/**
*隱私數據類型枚舉
*/
@Getter
publicenumPrivacyTypeEnum{

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

/**姓名*/
NAME,

/**身份證號*/
ID_CARD,

/**手機號*/
PHONE,

/**郵箱*/
EMAIL,
}

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

2. 創建自定義隱私注解: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;

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

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

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

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

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

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

3. 創建自定義序列化器: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);
}
}

這里是具體的實現過程,因為要脫敏的數據都是 String 類型的,所以繼承 JsonSerializer 時的類型填 String

重寫的 serialize 方法是實現脫敏的核心,根據類型 type 的不同去設置序列化后的值

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

4. 隱私數據隱藏工具類: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左側需要保留幾位明文字段
*@paramsuffixNoMaskLen右側需要保留幾位明文字段
*@parammaskStr用于遮罩的字符串,如'*'
*@return脫敏后結果
*/
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("張三三"));
}
}

這個工具類其實可以自己定,根據自己的業務去擴展,提一點:

在自定義注解 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;
}

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

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

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







審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • MySQL
    +關注

    關注

    1

    文章

    804

    瀏覽量

    26530
  • SpringBoot
    +關注

    關注

    0

    文章

    173

    瀏覽量

    177

原文標題:僅需一個注解,實現 SpringBoot 項目中的隱私數據脫敏!

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

收藏 人收藏

    評論

    相關推薦

    SpringBoot 如何實現熱部署

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

    SpringBoot項目數據源配置數據

    SpringBoot項目數據源配置
    發表于 06-05 09:51

    怎樣去使用springboot

    怎樣去使用springboot?學習springboot需要懂得哪些?
    發表于 10-25 07:13

    SQL/JAVA/mybatisplus數據脫敏實現原理

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

    如何在SpringBoot項目中實現動態定時任務

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

    數據脫敏技術定義及實施過程解析

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

    SpringBoot日志脫敏的方式介紹

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

    SpringBoot實現多線程

    SpringBoot實現多線程
    的頭像 發表于 01-12 16:59 ?1814次閱讀
    <b class='flag-5'>SpringBoot</b><b class='flag-5'>實現</b>多線程

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

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

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

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

    如何實現一個注解進行數據脫敏

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

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

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

    什么是數據脫敏?常用的脫敏規則有哪些

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

    SpringBoot采用JsonSerializer和Aop實現可控制的數據脫敏

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

    數據脫敏的3種常見方案,好用到爆!

    數據脫敏插件,目前支持地址脫敏、銀行卡號脫敏、中文姓名脫敏、固話脫敏、身份證號
    的頭像 發表于 02-25 16:14 ?1788次閱讀
    <b class='flag-5'>數據</b><b class='flag-5'>脫敏</b>的3種常見方案,好用到爆!
    主站蜘蛛池模板: 又紧又大又爽精品一区二区| 亚洲精品国产SUV| 色婷婷激情AV精品影院| 日韩影院久久| 涩涩在线视频| 亚洲精品成人a在线观看| 伊人久久99热这里只有精品| 中文字幕乱偷无码AV蜜桃| 99亚偷拍自图区亚洲| 成年免费三级视频| 国产欧洲野花A级| 久久草香蕉频线观| 欧美高清另类video| 色噜噜噜噜亚洲第一| 亚洲精品久久久992KVTV| 中国拍三a级的明星女| 波多野结衣 熟女| 国产品无码一区二区三区在线| 久久精品AV麻豆| 欧美成人免费一区二区三区不卡| 天天摸夜添狠狠添高| 亚洲三级黄色| bl(高h)文| 国产一级特黄aa毛片| 免费A级毛片无码无遮挡| 区久久AAA片69亚洲| 亚洲国产成人私人影院| 97国产蝌蚪视频在线观看| 国产成人欧美日韩在线电影 | 91看片淫黄大片.在线天堂| 纯h超级大尺度小黄文| 黑人干日本美女| 欧美日韩国产高清综合二区| 亚洲 欧美 中文字幕 在线| 2020美女视频黄频大全视频| 国产福利视频一区二区| 久久成人国产精品一区二区| 日夜啪啪一区二区三区| 一区二区视频在线观看高清视频在线 | 亚洲欧美精品一中文字幕| 99热这里只有精品88|