正则表达式之密码验证

对于门户网站,用户注册或修改密码时,需要有正则表达式验证密码,根据安全级别不同,网站会设置不同基本的密码正则表达式。
而此文主要通过一个实例,来讲解密码正则表达式中使用的特殊正则语法,如?! 、?= 等(Java代码验证)。

密码强度要求

  1. 至少包含一个数字,一个字母,一个特殊字符
  2. 密码长度在8~18之间

特殊正则语法

  1. Java 8 API中Pattern类对特殊正则语法的描述
  2. 正则字符详细说明
字符 说明
* 零次或多次匹配前面的字符或子表达式。例如,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

密码正则表达式

  1. 正向断言: 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!@#$_&*+-]就限定了只能包含数字、字母、特殊字符。
  2. 反向断言: 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()) );
			}
		}
	}
}
  1. 正向测试结果
=====testRegexPositive====
1234asdf
1234asdf not matched! length = 8
asdf@w1
asdf@w1 not matched! length = 7
asdf@w12
asdf@w12 matched! length = 8
  1. 反向测试结果
=====testNegative====
1234asdf
1234asdf not matched! length = 8
1234asd
1234asd not matched! length = 7
1234asd#
1234asd# matched! length = 8
posted @ 2018-10-22 16:26  一弓一土两亩田  阅读(3819)  评论(0编辑  收藏  举报