2008年7月20日

驗證密碼的 Regular Expression

好久沒寫技術文章了,來寫一下最近遇到的 Case,利用 Regular Expression 驗證密碼,密碼長度在 6-30 字元內,且要包含數字、英文字,網路上查到的 Pattern 如下

^(?=.*\d)(?=.*[a-zA-Z]).{6,30}$

有人說這是罵人的話,哈,看起來真像。

先來驗證一下是否正確,先到 RegEx: online regular expression testingRegular Expression 輸入上面那一串密文,Test String #1 輸入想驗證的字串,按下 Test 出現驗證結果,這個網站好用的地方在驗證結果會很貼心的把 Java 跟 Regular Expression 有關的 Method 的驗證結果都列出來。

測試沒問題後接著就來了解一下這串外星文在寫些什麼

.:表示任意一個字元,在 Java 中除了 "\r""\n" 外都包括。
*:表示前面那個 Pattern 出現 0 或一次以上。
.*:表示非 "\r""\n" 字元出現了 0 或一次以上。
\d:表示數字 0-9,也可以寫成 [0-9]
.*\d:表示非 "\r""\n" 字元出現了 0 或一次以上,再跟著一個數字,可以驗證字串中有出現過數字,不管在任何位置。
(?=.*\d):這是 Positive Lookahead,用來判斷右邊緊接著的字元是否符合比對條件,如果符合條件才會繼續比對下去。拿這個實例來說,右邊的字元必須包含一個數字才算符合這個條件。
[a-zA-Z]:表示英文字母,大小寫都包含在內。
.*[a-zA-Z]:表示非 "\r""\n" 字元出現了 0 或一次以上,再跟著一個英文字母,可以驗證字串中有出現過英文字母,不管在任何位置。
(?=.*[a-zA-Z]):跟上面出現過得 Positive Lookahead 一樣,這是說右邊的字必須包含一個 a 到 z 或是 A 到 Z 的字元,說穿了就是右邊的字要包含一個英文字的意思。
.{6,30}:表示字串長度要大於等於 6,小於等於 30。
^:表示字首,意思就是說後面的字必須是從字首開始。
$:表示字尾,表示前面的字要是字尾。

解釋完畢,到這裡原本就不懂的人應該還是不懂,原本就懂的人會覺得這是垃圾文,半懂的人應該會有點收穫,但腦海中應該會浮出更多疑惑。

在測試完這神奇的外星文可以正確的達到我想要得效果後,去網路上找了一些資料,發覺 Regular Expression 真強大,一堆看不懂的符號交錯在一起就可以完成驗證的工作,這就像 SQL 一樣,要常寫、常練習才會寫得好、寫得漂亮。因此解釋完有更多疑惑是正常的。

想更了解的可以參考 JavaWorld 上有一篇 Java Regular Expression的學習筆記,寫得算很淺顯易懂。最後放上驗證的程式碼供參考

public boolean isPwValid() {
String pw = getSysUser().getPassword();
String pattern = "^(?=.*[a-zA-Z]+)(?=.*\\d+)[a-zA-Z0-9]{6,16}$";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(pw);
return m.matches();
}

很意外不是用 Jakarta 的 RegExp 套件吧,原來 Java 中藏了這麼好用的 Class。

3 則留言:

  1. 看不太懂..
    1. "(?=.*\d)" 拿這個實例來說,右邊的字元必須包含一個數字才算符合這個條件
    問題: 如你所說,所以一開始一定要先有數字?譬如:f123456就是false??

    2. "^":表示字首,意思就是說後面的字必須是從字首開始。
    問題:不加行嗎?既然都有"(?=.*\d)"了,他到底是作用在哪的阿?

    3."$",這邊我也看不懂,如果說[1]$是指所有1開頭的字串嗎?21可以嗎?
    不然為什麼一開始下 "(?=.*\d)"

    回覆刪除
  2. 大概看懂了!

    一樓如果不懂可以看看這邊哦~
    wiki裡面有蠻詳細的說明.
    http://zh.wikipedia.org/w/index.php?title=%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F&variant=zh-tw

    回覆刪除

Related Posts Plugin for WordPress, Blogger...