[轉][ASP.Net]Regular Expression的驗証

[轉][ASP.Net]Regular Expression的驗証

其實用Regular Expression做密碼複雜度的驗證已不是什麼創舉,用google輸入關鍵字"regular expression password"就會有一堆參考。
由於(?=)和(?!)的用法之前有在這篇文章大略提過,所以此篇就當做是為了避免自己忘掉,且做為衍生應用寫的吧。
關於密碼驗證的Regular Expression,我自己在網路上找到的是以下這個:

^.*(?=.{10,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

上述的Regular Expression可達到以下幾個驗證密碼的項目:

  1. (?=.{10,}):密碼長度10個以上
  2. (?=.*\d):至少要有一個0-9的數字
  3. (?=.*[a-z]):至少要有一個小寫的英文字母(a-z)
  4. (?=.*[A-Z]]):至少要有一個大寫的英文字母(A-Z)
  5. (?=.*[@#$%^&+=]):至少要有清單中的一個特殊符號(@#$%^&+=)

要看懂以上的Regular Expression,可以到Wikipedia的Syntax章節參考一下。
技巧上很簡單,把每個(?=)項目都當做個驗證的關卡來看,要通過這個密碼驗證,就要每一關都通過。
至於整個Regular Expression最後面的.*是一定要有的,前面的.*可有可無;如果兩個都沒有,或是只有前面有.*,都是不行的。(有興趣的可以多方嘗試)
以下說明一下各個驗證的項目:(記住:不管是(?=)或(?!),.*都記得先放進去)

  • (?=.{10,}):檢查輸入的字元長度是否有超過10。如果資料庫裡的密碼欄位長度是20,那就改成(?=.{10,20})
  • (?=.*\d):因為\d表示[0-9],所以此部分是檢查輸入的字串裡有沒有0-9的數字。
  • (?=.*[a-z])(?=.*[A-Z]):概念同(?=.*\d),不過這是分開檢查有沒有輸入大寫與小寫英文字母。如果只是要有英文字母,就改成(?=.*[a-zA-Z])
  • (?=.*[@#$%^&+=]):要使用者輸入至少一個指定的特殊符號。有人會用(?=.*\W)來表示,因為\W表示[^A-Za-z0-9_],這邊要注意\W有排除掉"_"這個符號。


上述的密碼驗證在大部分情況都適用,不過要找碴的話,就是這個Regular Expression允許輸入雙字元。
由於大多數的程式設計師不會將密碼欄位的資料型態訂成nvarchar,所以我們可以再多加一個不允許雙字元輸入的判斷,以避免真的有人來亂的。
這時候就要參考一下ASCII 字元表,查一下要排除的字元有哪些。
如果只是要排除雙字元,那麼就多加一個以下的判斷:

(?!.*[^\x00-\xff]):表示不允許輸入ASCII以外的字元。

不過,也許有人發現,ASCII字元表中,也不是所有的字元都應該要接受。
至少我認為\x00到\x20,以及\x7F到\xFF這個範圍內的都不需要,只有\x21到\x7E的部分是可接受輸入的。
所以可以再修改一下上面僅允許ASCII的驗證,改成如下的驗證:

(?!.*[^\x21-\x7e]):表示不允許輸入\x21到\x7E以外的字元。

最後,我密碼驗證的Regular Expression如下:
 

^(?!.*[^\x21-\x7e])(?=.{4,10})(?=.*[\W])(?=.*[a-zA-Z])(?=.*\d).*$

上述的Regular Expression可達到以下幾個驗證密碼的項目(依序):

  1. 不允許特殊符號、數字、英文字母以外的字元輸入
  2. 密碼長度4到10個字元
  3. 至少要有一個特殊符號
  4. 至少要有一個大寫或小寫的英文字母
  5. 至少要有一個0-9的數字

上面所列的Regular Expression,可以用在RegularExpressionValidator的ValidationExpression屬性。
不過要注意的是,在Web用的Regular Expression跟透過C#或VB的Regex物件做出的判斷會有不一樣的地方。
例如,將長度驗證的部分拿到(?=)以外的地方去做,如下例:

^(?!.*[^\x21-\x7e])(?=.*[\W])(?=.*[a-zA-Z])(?=.*\d).{4,10}$

在RegularExpressionValidator中,輸入"111!!@A"會驗證不過,但改成"111!!@A@1A"卻又可驗證過。
而在C#的程式中,以下兩個都會回傳True:
 

  1. Regex regex = new Regex(@"^(?!.*[^\x21-\x7e])(?=.*[\W])(?=.*[a-zA-Z])(?=.*\d).{4,10}$");   
  2. Console.WriteLine(regex.IsMatch("111!!@A"));   
  3. Console.WriteLine(regex.IsMatch("111!!@A@1A"));  

所以,個人建議將所有的判斷都寫在(?=)或(?!)中

 

ps:

密碼長度6,包含英數字

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

密碼長度6,英數字再加上包含大小寫

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

 

FROM: http://www.dotblogs.com.tw/yilinliu/archive/2009/06/03/8655.aspx 

這邊也講的很詳細..http://phone.idv.tw/cs2/forums/thread/424.aspx

http://blog.xuite.net/yan.kee/CSharp/25150950-%5B%E8%BD%89%5D%5BASP.Net%5DRegular+Expression%E7%9A%84%E5%AF%86%E7%A2%BC%E9%A9%97%E8%AD%89+