自定義密碼規則功能實現

前言

最近遇到一個功能需要用戶可以自定義系統的密碼規則,傳統中對於密碼規則這塊一般都是後端給定常用的密碼正則表達式,然後當用戶註冊的時候填寫密碼,系統獲取密碼後會匹配這個給定的正則表達式,如果不匹配會提示用戶密碼不符合規範。

現在如果是可以自定義密碼規則,首先不太可能由用戶直接寫正則表達式,難度較大且正則表達式的正確性無法得到保證。通過分析一般密碼的正則表達式發現基本都是數字、大小寫字母、特殊字符以及規定密碼的長度,所以如果自定義規則的話不妨讓用戶可以自定義密碼中數字、大小寫這些字段的長度,然後系統讀取這些長度後生成一個正則表達式,然後就和傳統的密碼匹配一樣。

之前都是直接使用SpringBoot自帶的@Pattern註解,然後直接手動定死正則表達式,現在多了個正則表達式生成的過程,學到了一些東西,現進行簡單記錄。

參考鏈接

1. 密碼規則自定義:https://blog.csdn.net/socalabo/article/details/82924858

2. 正則表達式:

https://blog.csdn.net/s275287998/article/details/102488773

https://www.cnblogs.com/ryanace1988/p/11082961.html

https://www.runoob.com/regexp/regexp-syntax.html

3. 隨機生成密碼:

https://blog.csdn.net/hero_lxz/article/details/79754998

https://blog.csdn.net/Yuriey/article/details/82491122

實現過程

1.根據字段生成正則表達式

設置用戶可以自定義密碼的最小長度、最大長度、數字最小長度、大小寫字母最小長度、特殊符號的最小長度。然後根據每個字段拼接生成正則表達式。

至少1個數字:

(?=.*\d)

或者

(?=.*[0-9])

至少一個小寫字母:

(?=.*[a-z])

至少一個大寫字母:

(?=.*[A-Z])

至少一個特殊字符:此處列舉的是鍵盤上的除開數字字母的字符,有其他字符直接添加進去即可

(?=.*?[#?!@$%^&*-_])

但是實際中有時候出現至少兩位數字這種情況,所以進行改造:

以數字爲例,至少n位數字,以兩位爲例:其他大/小寫字母、特殊字符同數字

(?=.*[0-9].*[0-9])

根據獲取的密碼各字段長度,完成各部分正則表達式的構成,最後實現整體密碼正則表達式的拼接,舉例:至少2位數字、1位特殊字符,2位小寫字母,0位大寫字母,密碼長度至少爲6至多爲10

^(?=.*[0-9]*[0-9])(?=.*[a-z].*[a-z])(?=.*?[#?!@$%^&*-_]).{6,10}$

上述正則表達式不限定字符出現的順序,即只要保證密碼中有這些最小個數的字符即可。代碼實現中根據不同字段不同的長度分別進行拼接即可,此處不再贅述。

3. 密碼匹配

密碼匹配直接使用matches方法即可,或許用戶的密碼然後調用matches方法,方法參數爲生成的這個正則表達式即可

拓展

1. 隨機生成密碼

隨機生成密碼就是根據系統規則然後分別隨機取密碼的長度、各個字段的長度、各個類型字段在密碼中的位置、各個字段的具體值。

隨機使用Random類,Random中使用方法nextInt(n)方法獲取[0,n)範圍的隨機值,隨機生成密碼各部分的隨機可抽象出一個方法,根據上下限來獲取隨機的n

/**
     * 隨機獲取一個指定範圍的數字 [0,max-min+1)+min=[min,max+1)=[min.max]
     * @return
     */
    public int getRandomInt(int min,int max){
        return random.nextInt(max-min+1)+min;
    }

大寫字母、小寫字母根據在ASCII中的編碼值確定隨機n,特殊字符在枚舉中的特殊字符中隨機下標取一個值即可,數字在0-9中取一個隨機值。

/**
     * 隨機獲取一個特殊字符
     */
    public String getRandomSpecialLetter(){
        char[] chars = {'`', '~', '@', '#', '$', '%', '^', '&',
                '*', '(', ')', '-', '_', '=', '+', '[',
                '{', '}', ']', '\\', '|', ';', ':', '"',
                '\'', ',', '<', '.', '>', '/', '?'};
        return String.valueOf(chars[random.nextInt(chars.length)]); //數組的索引從0開始,random同
    }

/**
     * 隨機獲取一個0-9的數字
     */
    public int getRandomDigit(){
        return getRandomInt(0,9);
    }

/**
     * 隨機獲取一個大寫字母
     */
    public char getRandomUpper(){
        return (char)getRandomInt(65,90);
    }

/**
     * 隨機獲取一個小寫字母
     * @return
     */
    public char getRandomLower(){
        return getRandomInt(97,122);
    }

各字段密碼在整段密碼中的隨機位置,通過定義一個Map集合,然後隨機取下標賦字段值即可。

        //定義隨機密碼中各字段在整個密碼的位置
        Map<Integer,String> indexMap=new HashMap<Integer,String>();
        while(indexMap.size()<upperNum){
            //確定大寫字母在整段密碼中的索引號
            int rint=getRandomInt(0, pwdLength-1);
            if(indexMap.get(rint)==null){
                indexMap.put(rint, "upper");
            }
        }
        while(indexMap.size()<upperNum+lowerNum){
            //確定小寫字母的索引號
            int rint=getRandomInt(0, pwdLength-1);
            if(indexMap.get(rint)==null){
                indexMap.put(rint, "lower");
            }
        }
        //...其他字段類似

2. 密碼加密

加密可以使用PasswordEncoder類,使用其encode方法,方法參數爲密碼,將密碼加密

知識點總結

1. 正則表達式

2. JSON與Java對象互轉

https://blog.csdn.net/qq_38586378/article/details/103001255

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.40</version>
        </dependency>
ObjectMapper mapper = new ObjectMapper();
//Java轉JSON
String jsonStr = mapper.writeValueAsString(Object obj); //一般需要捕獲處理JsonProcessingException異常
//JSON轉Java
Object obj = mapper.readValue(jsonStr,Object.class)

總結

拿到功能先理用戶邏輯,然後將功能分步最後按步驟實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章