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

SpringBoot?自定義注解之脫敏注解詳解

 更新時(shí)間:2021年12月18日 09:53:59   作者:我是太陽(yáng)男神  
這篇文章主要介紹了SpringBoot?自定義注解之脫敏注解詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

自定義注解之脫敏注解

數(shù)據(jù)脫敏是指對(duì)某些敏感信息通過脫敏規(guī)則進(jìn)行數(shù)據(jù)的變形,實(shí)現(xiàn)敏感隱私數(shù)據(jù)的可靠保護(hù)。需求是把返回到前端的數(shù)據(jù)進(jìn)行脫敏,以免造成隱私信息的泄露。

一、脫敏后的效果

未脫敏前

這樣顯示很不好吧,所有信息都泄露了

脫敏后

這樣就很好了吧

二、代碼

1.脫敏注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveSerialize.class)
public @interface Sensitive {
    /**
     * 脫敏數(shù)據(jù)類型
     */
    SensitiveTypeEnum type() default SensitiveTypeEnum.CUSTOMER;
    /**
     * 前置不需要打碼的長(zhǎng)度
     */
    int prefixNoMaskLen() default 0;
    /**
     * 后置不需要打碼的長(zhǎng)度
     */
    int suffixNoMaskLen() default 0;
    /**
     * 用什么打碼
     */
    String symbol() default "*";
}

2.定義脫敏類型

public enum SensitiveTypeEnum {
    /**
     * 自定義
     */
    CUSTOMER,
    /**
     * 姓名
     */
    NAME,
    /**
     * 身份證
     */
    ID_NUM,
    /**
     * 手機(jī)號(hào)碼
     */
    PHONE_NUM
}

3.敏感工具類

public class DesensitizedUtils {
    /**
     * 對(duì)字符串進(jìn)行脫敏操作
     *
     * @param origin          原始字符串
     * @param prefixNoMaskLen 左側(cè)需要保留幾位明文字段
     * @param suffixNoMaskLen 右側(cè)需要保留幾位明文字段
     * @param maskStr         用于遮罩的字符串, 如'*'
     * @return 脫敏后結(jié)果
     */
    public static String desValue(String origin, int prefixNoMaskLen, int suffixNoMaskLen, String maskStr) {
        if (origin == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        for (int i = 0, n = origin.length(); i < n; i++) {
            if (i < prefixNoMaskLen) {
                sb.append(origin.charAt(i));
                continue;
            }
            if (i > (n - suffixNoMaskLen - 1)) {
                sb.append(origin.charAt(i));
                continue;
            }
            sb.append(maskStr);
        }
        return sb.toString();
    }
    /**
     * 【中文姓名】只顯示最后一個(gè)漢字,其他隱藏為星號(hào),比如:**夢(mèng)
     *
     * @param fullName 姓名
     * @return 結(jié)果
     */
    public static String chineseName(String fullName) {
        if (fullName == null) {
            return null;
        }
        return desValue(fullName, 1, 0, "*");
    }
    /**
     * 【身份證號(hào)】顯示前4位, 后2位,其他隱藏。
     *
     * @param id 身份證號(hào)碼
     * @return 結(jié)果
     */
    public static String idCardNum(String id) {
        return desValue(id, 4, 2, "*");
    }
    /**
     * 【手機(jī)號(hào)碼】前三位,后四位,其他隱藏。
     *
     * @param num 手機(jī)號(hào)碼
     * @return 結(jié)果
     */
    public static String mobilePhone(String num) {
        return desValue(num, 3, 4, "*");
    }
}

4.脫敏序列化信息

@NoArgsConstructor
@AllArgsConstructor
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {
    /**
     * 脫敏類型
     */
    private SensitiveTypeEnum sensitiveTypeEnum;
    /**
     * 前幾位不脫敏
     */
    private Integer prefixNoMaskLen;
    /**
     * 最后幾位不脫敏
     */
    private Integer suffixNoMaskLen;
    /**
     * 用什么打碼
     */
    private String symbol;
    @Override
    public void serialize(final String origin, final JsonGenerator jsonGenerator,
                          final SerializerProvider serializerProvider) throws IOException {
        switch (sensitiveTypeEnum) {
            case CUSTOMER:
                jsonGenerator.writeString(DesensitizedUtils.desValue(origin, prefixNoMaskLen, suffixNoMaskLen, symbol));
                break;
            case NAME:
                jsonGenerator.writeString(DesensitizedUtils.chineseName(origin));
                break;
            case ID_NUM:
                jsonGenerator.writeString(DesensitizedUtils.idCardNum(origin));
                break;
            case PHONE_NUM:
                jsonGenerator.writeString(DesensitizedUtils.mobilePhone(origin));
                break;
            default:
                throw new IllegalArgumentException("unknown sensitive type enum " + sensitiveTypeEnum);
        }
    }
    @Override
    public JsonSerializer<?> createContextual(final SerializerProvider serializerProvider,
                                              final BeanProperty beanProperty) throws JsonMappingException {
        if (beanProperty != null) {
            if (Objects.equals(beanProperty.getType().getRawClass(), String.class)) {
                Sensitive sensitive = beanProperty.getAnnotation(Sensitive.class);
                if (sensitive == null) {
                    sensitive = beanProperty.getContextAnnotation(Sensitive.class);
                }
                if (sensitive != null) {
                    return new SensitiveSerialize(sensitive.type(), sensitive.prefixNoMaskLen(),
                            sensitive.suffixNoMaskLen(), sensitive.symbol());
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(null);
    }
}

小結(jié)一下

該注解用于隱私數(shù)據(jù)的脫敏,只作用于類的屬性上。該注解有四個(gè)屬性,type表示脫敏數(shù)據(jù)類型(默認(rèn)為CUSTOMER自定義,后面三個(gè)屬性才有效),prefixNoMaskLen表示前置不需要打碼的長(zhǎng)度(默認(rèn)為0),suffixNoMaskLen表示后置不需要打碼的長(zhǎng)度(默認(rèn)為0),symbol表示用什么打碼(默認(rèn)為*)。

一般用于返回對(duì)象給前端對(duì)象中包含隱私數(shù)據(jù)例如身份證、詳細(xì)地址需要進(jìn)行脫敏的情況。

示例:

public class UserInfo {
    @Sensitive(type = SensitiveTypeEnum.NAME)
    private String name;
    @Sensitive(type = SensitiveTypeEnum.ID_NUM)
    private String idNum;
    @Sensitive(type = SensitiveTypeEnum.PHONE_NUM)
    private String phone;
    @Sensitive(type = SensitiveTypeEnum.CUSTOMER, prefixNoMaskLen = 3, suffixNoMaskLen = 2, symbol = "#")
    private String address;
    @Sensitive(prefixNoMaskLen = 1, suffixNoMaskLen = 2, symbol = "*")
    private String password;
}

如果還有疑問我寫了個(gè)demo,可以下載下來運(yùn)行看看

鏈接: 脫敏注解demo.

自己手寫的一個(gè)高效自定義字符串脫敏注解

經(jīng)理要求寫一個(gè)自定義脫敏注解,百度查了一堆。都是效率比較低的

自己寫了個(gè) 僅供參考

/**
 * description: 數(shù)據(jù)脫敏
 * 1、默認(rèn)不傳部位、不傳顯示*號(hào)數(shù)量時(shí)字段全部脫敏
 *
 * 原始字符串 adminis 總長(zhǎng)度從0計(jì)算 總數(shù)6
 * index=(0,2) size = 1 下標(biāo)即從0到2以內(nèi)的字符標(biāo)注“ * ”,size=1 則只填充一個(gè)* size 不能超過截取字符
 * index=(2,3) size =2 下標(biāo)即從2到3以內(nèi)的字符標(biāo)注“ * ”,size=2 則只填充二個(gè)* size 不能超過截取字符
 *
 * date: 2020/3/13 15:56
 *
 * @author oakdog
 * @version 1.0
 */
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = Desensitization.ConvertDesensitization.class)
public @interface Desensitization {
    /**
     * 	傳入的下標(biāo)索引
     * 	規(guī)則 第一位起始下標(biāo) 第二位是結(jié)束下標(biāo) 默認(rèn)值6位下標(biāo)
     **/
    int[] index() default {0,6};
    /**
     * 	需要脫敏的字符長(zhǎng)度
     * 	規(guī)則 輸入 3 :則根據(jù)index下標(biāo)索引對(duì)應(yīng)脫敏3個(gè)字符 默認(rèn)6個(gè)長(zhǎng)度脫敏
     **/
    int size() default 6;
    class ConvertDesensitization extends StdSerializer<Object> implements ContextualSerializer {
        private int[] index;
        private int size;
        public ConvertDesensitization() {
            super(Object.class);
        }
        private ConvertDesensitization(int[] index,int size) {
            super(Object.class);
            this.size = size;
            this.index = index;
        }
        @Override
        public void serialize(Object value, JsonGenerator jgen,
                              SerializerProvider provider) throws IOException {
            char[] str = value.toString().toCharArray();
            StringBuilder builder = new StringBuilder();
            String char1 = (String) value;
            if(str.length > 0) {
                //字符長(zhǎng)度超長(zhǎng)處理
                if(index[0] < str.length && index[1] < str.length) {
                    //使用默認(rèn)初始值的脫敏處理
                    if(index[0] == 0) {
                        //如果輸入脫敏大小長(zhǎng)度小于0或大于原始脫敏字符長(zhǎng)度,則全脫敏字符
                        if (size < 0 || size < str.length) {
                            char[] charStr = char1.substring(index[1], str.length).toCharArray();
                            char[] charStr1 = char1.substring(index[0], index[1]).toCharArray();
                            builder.append(charStr1);
                            for (int i = 0; i < charStr.length; i++) {
                                if(size > i) {
                                    builder.append("*");
                                }else {
                                    builder.append(charStr[i]);
                                }
                            }
                        }else {
                            builder.append(getDefaultChar((String) value,"left"));
                        }
                    }else {
                        //從中間位置截取脫敏處理
                        //如果輸入脫敏大小長(zhǎng)度小于0或大于原始脫敏字符長(zhǎng)度,則全脫敏字符
                        if (size < 0 || size < str.length) {
                            char[] charStr = char1.substring(index[0], str.length - index[1] + 1).toCharArray(); //2 6-4 2 //中間截取部分
                            List<Integer> prefix = getPrefix(index[0], (String) value);
                            //List<Integer> suffix = getSuffix(index[0],index[1], (String) value);
                            for (Integer integer : prefix) {
                                builder.append(str[integer]);
                            }
                            for (int i = 0; i < charStr.length; i++) {
                                if (size > i) {
                                    builder.append("*");
                                } else {
                                    builder.append(charStr[i]);
                                }
                            }
                            char[] chars = Arrays.copyOfRange(str, index[1], str.length);
                            builder.append(String.valueOf(chars));
                        }else {
                            builder.append(getDefaultChar((String) value,"right"));
                        }
                    }
                }else {
                    //默認(rèn)處理
                    builder.append(getDefaultChar((String) value,""));
                }
            }
            jgen.writeString(builder.toString());
        }
        /**
         * 默認(rèn)的填充方式
         * @param str 原始字符串
         * @param position 位置
         * @return
         */
        String getDefaultChar(String str,String position){
            char[] desensitizationStr = str.toCharArray();
            for(int i=0;i<desensitizationStr.length;i++){
                if("left".equals(position)){
                    if(i != 0){
                        desensitizationStr[i] = '*';
                    }
                }else if("right".equals(position)){
                    if(i != desensitizationStr.length-1){
                        desensitizationStr[i] = '*';
                    }
                }else {
                    if(i != 0 && i != desensitizationStr.length-1){
                        desensitizationStr[i] = '*';
                    }
                }
            }
            return String.valueOf(desensitizationStr);
        }
        /**
         * 獲取字符前綴下標(biāo)
         * @param index 下標(biāo)
         * @param val 原始字符串
         * @return
         */
        List<Integer> getPrefix(int index,String val){
            //int[] chars = {};
            List<Integer> listIndex = new ArrayList<>();
            for(int i=0;i<val.length();i++){
                if(i != index){ //0 1 != 2
                    listIndex.add(i);
                    continue;
                }
                break;
            }
            return listIndex;
        }
        @Override
        public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
            int[] index = {0,6}; //初始值
            int size = 6; //初始值
            Desensitization ann = null;
            if (property != null) {
                ann = property.getAnnotation(Desensitization.class);
            }
            if (ann != null) {
                index = ann.index();
                size = ann.size();
            }
            return new Desensitization.ConvertDesensitization(index,size);
        }
    }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題

    關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題

    這篇文章主要給大家分享的是關(guān)于Java Interface接口的簡(jiǎn)單練習(xí)題,難度不算大,但是要有一個(gè)清晰的邏輯建立接口和鏈接Java類。下面來看看文章的詳細(xì)介紹吧,需要的朋友可以參考一下
    2021-11-11
  • java代碼關(guān)閉tomcat程序及出現(xiàn)問題解析

    java代碼關(guān)閉tomcat程序及出現(xiàn)問題解析

    這篇文章主要介紹了java代碼關(guān)閉tomcat程序 及出現(xiàn)問題解析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2019-05-05
  • Java多線程學(xué)習(xí)筆記

    Java多線程學(xué)習(xí)筆記

    常用的實(shí)現(xiàn)多線程的兩種方式:Thread和Runnable。之所以說是“常用”,是因?yàn)樵贘ava 5后可以通過java.util.concurrent包中的線程池來實(shí)現(xiàn)多線程
    2021-09-09
  • Java二分算法題目練習(xí)實(shí)戰(zhàn)教程

    Java二分算法題目練習(xí)實(shí)戰(zhàn)教程

    二分查找(Binary?Search)是一種非常高效的查找算法,它在有序數(shù)組或有序列表中通過反復(fù)將搜索范圍分為兩半來查找目標(biāo)元素,這篇文章主要介紹了Java二分算法題目練習(xí)的相關(guān)資料,需要的朋友可以參考下
    2025-11-11
  • Java基礎(chǔ)類庫(kù)之StringBuffer類用法詳解

    Java基礎(chǔ)類庫(kù)之StringBuffer類用法詳解

    String類是在所有開發(fā)項(xiàng)目開發(fā)之中一定會(huì)使用的一個(gè)功能類。雖然String類很好用,但也有弊端——內(nèi)容不允許頻繁修改,所以為了解決問題,我們提供了StringBuffer類。本文就來講講StringBuffer類的用法
    2022-07-07
  • Java中Runnable和Thread的區(qū)別分析

    Java中Runnable和Thread的區(qū)別分析

    在java中可有兩種方式實(shí)現(xiàn)多線程,一種是繼承Thread類,一種是實(shí)現(xiàn)Runnable接口,下面就拉分別介紹一下這兩種方法的優(yōu)缺點(diǎn)
    2013-03-03
  • Mybatis核心配置文件加載流程詳解

    Mybatis核心配置文件加載流程詳解

    本文將介紹MyBatis在配置文件加載的過程中,如何加載核心配置文件、如何解析映射文件中的SQL語(yǔ)句以及每條SQL語(yǔ)句如何與映射接口的方法進(jìn)行關(guān)聯(lián),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • Java實(shí)現(xiàn)將PDF文件拆分成多個(gè)PDF文檔

    Java實(shí)現(xiàn)將PDF文件拆分成多個(gè)PDF文檔

    在處理PDF文檔時(shí),我們經(jīng)常需要將一個(gè)大型PDF文件按特定頁(yè)數(shù)或章節(jié)拆分成多個(gè)獨(dú)立文檔,下面我們就來看看如何使用Java進(jìn)行PDF文件拆分吧
    2025-09-09
  • Java的注解原理詳解

    Java的注解原理詳解

    這篇文章主要介紹了Java的注解原理詳解,注解是JDK1.5引入的新特性,包含在java.lang.annotation包中,它是附加在代碼中的一些元信息,將一個(gè)類的外部信息與內(nèi)部成員聯(lián)系起來,在編 譯、運(yùn)行時(shí)進(jìn)行解析和使用,需要的朋友可以參考下
    2023-10-10
  • Java精確抽取網(wǎng)頁(yè)發(fā)布時(shí)間

    Java精確抽取網(wǎng)頁(yè)發(fā)布時(shí)間

    這篇文章主要為大家詳細(xì)介紹了Java精確抽取網(wǎng)頁(yè)發(fā)布時(shí)間的相關(guān)資料,盡量做到精確無(wú)誤,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評(píng)論

通江县| 灌云县| 拉孜县| 崇明县| 曲沃县| 板桥市| 达拉特旗| 桃江县| 富顺县| 云龙县| 合阳县| 简阳市| 密云县| 卓资县| 遂平县| 山东| 旬阳县| 德庆县| 淄博市| 根河市| 大庆市| 哈密市| 罗平县| 綦江县| 讷河市| 民权县| 马关县| 泾川县| 新闻| 大方县| 张北县| 德庆县| 嘉祥县| 青阳县| 漾濞| 福贡县| 鹤岗市| 金乡县| 文水县| 光山县| 静海县|