對於門戶網站,用戶注冊或修改密碼時,需要有正則表達式驗證密碼,根據安全級別不同,網站會設置不同基本的密碼正則表達式。
而此文主要通過一個實例,來講解密碼正則表達式中使用的特殊正則語法,如?! 、?= 等(Java代碼驗證)。
密碼強度要求
- 至少包含一個數字,一個字母,一個特殊字符
- 密碼長度在8~18之間
特殊正則語法
- Java 8 API中Pattern類對特殊正則語法的描述
- 正則字符詳細說明
字符 | 說明 |
---|---|
* | 零次或多次匹配前面的字符或子表達式。例如,zo* 匹配"z"和"zoo"。* 等效於 {0,}。 |
+ | 一次或多次匹配前面的字符或子表達式。例如,"zo+"與"zo"和"zoo"匹配,但與"z"不匹配。+ 等效於 {1,}。 |
? | 零次或一次匹配前面的字符或子表達式。例如,"do(es)?"匹配"do"或"does"中的"do"。? 等效於 {0,1}。 |
. | 匹配除"\r\n"之外的任何單個字符。若要匹配包括"\r\n"在內的任意字符,請使用諸如"[\s\S]"之類的模式。 |
(?=pattern) | 執行正向預測先行搜索的子表達式,該表達式匹配處於匹配 pattern 的字符串的起始點的字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,'Windows (?=95 |
(?!pattern) | 執行反向預測先行搜索的子表達式,該表達式匹配不處於匹配 pattern 的字符串的起始點的搜索字符串。它是一個非捕獲匹配,即不能捕獲供以后使用的匹配。例如,'Windows (?!95 |
密碼正則表達式
- 正向斷言: regex =
^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$_&*+-])[0-9a-zA-Z!@#$_&*+-]{8,18}$
解釋:根據上面的正則字符說明,先分析(?=.*[0-9])
, 其中?=pattern01
是正向先行搜索子表達,不獲取匹配,其實可以理解為斷言匹配的string能夠用pattern01
匹配到子表達,如果斷言成功,則就用剩下剩余的regex去匹配此string,否則regex即匹配不成功;
而.*[0-9]
表示匹配以數字結尾的字符串(即整個待匹配的字符串包含數字),所以(?=.*[0-9])
表示為斷言字符串包含數字,(?=.*[a-zA-Z])
斷言字符串包含字母,(?=.*[!@#$_&*+-])
斷言字符創包含特殊字符;若這三個斷言成功,就限定了string至少含有數字、字母、特殊字符;
而最后的[0-9a-zA-Z!@#$_&*+-]就限定了只能包含數字、字母、特殊字符。 - 反向斷言: regex =
^(?![a-zA-Z0-9]+$)(?![a-zA-Z!@#$%^_&*]+$)(?![0-9!@#$%^_&*]+$)[a-zA-Z0-9!@#$%^_&*]{8,18}$
解釋:(?![a-zA-Z0-9]+$)
表示不能只包含數字和字母,同理,三個反向斷言也可以限定至少包含一個數字、字母、特殊字符
代碼測試
public class HelloWorld {
public static void main(String []args) {
// testRegexPositive();
testRegexNegative();
}
public static void testRegexPositive() {
System.out.println("=====testRegexPositive====");
String reg = "^(?=.*[0-9])(?=.*[a-zA-Z])(?=.*[!@#$_&*+-])[0-9a-zA-Z!@#$_&*+-]{8,18}$";
Pattern pattern = Pattern.compile(reg);
Scanner sc = new Scanner(System.in);
while( sc.hasNext() ) {
String str = sc.nextLine();
Matcher matcher = pattern.matcher(str);
if ( matcher.matches() ) {
System.out.println( str + " matched! length = " + String.valueOf(str.length()) );
} else {
System.out.println( str + " not matched! length = " + String.valueOf(str.length()) );
}
}
}
public static void testRegexNegative() {
System.out.println("=====testNegative====");
String reg = "^(?![a-zA-Z0-9]+$)(?![a-zA-Z!@#$%^_&*]+$)(?![0-9!@#$%^_&*]+$)[a-zA-Z0-9!@#$%^_&*]{8,18}$";
Pattern pattern = Pattern.compile(reg);
Scanner sc = new Scanner(System.in);
while( sc.hasNext() ) {
String str = sc.nextLine();
Matcher matcher = pattern.matcher(str);
if ( matcher.matches() ) {
System.out.println( str + " matched! length = " + String.valueOf(str.length()) );
} else {
System.out.println( str + " not matched! length = " + String.valueOf(str.length()) );
}
}
}
}
- 正向測試結果
=====testRegexPositive====
1234asdf
1234asdf not matched! length = 8
asdf@w1
asdf@w1 not matched! length = 7
asdf@w12
asdf@w12 matched! length = 8
- 反向測試結果
=====testNegative====
1234asdf
1234asdf not matched! length = 8
1234asd
1234asd not matched! length = 7
1234asd#
1234asd# matched! length = 8