登录密码正则表达式

最近收到产品需求,需要对原邮件密码规则进行修改。
先由客户端修改密码规则,服务端后续才进行更新。
具体需求如下:

1
2
3
4
5
6
1.新密码必须包含大写字母、小写字母、数字、特殊字符任意3种组合
2.长度至少为8位
3.不能包含自身账号
4.不包含3位以上相同字符
5.不能是最近5次使用密码
6.特殊字符仅限.~!@$_

原有密码校验规则与新规则区别较大,且历史代码写得比较混乱,因此打算重新设计。
匹配规则还是挺复杂的,一步步来。

1
新密码必须包含大写字母、小写字母、数字、特殊字符任意3种组合

首先根据这条,网上很多正则表达式是这种:

1
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,}"

但是这种是至少包含至少一个大写字母,一个小写字母,一个数字和一个特殊字符,正则表达式里只有或,并不好区分”任意”这种说法。

因此实现思路是,需要分别设计大写字母、小写字母、数字、特殊字符的判断,再通过Pattern.match(regex, password)判断符合种数,大于3才表示匹配此规则。

其他特殊字符太多,无法进行排除,考虑换个方式,这样写可以设定取出以下字符:

1
[A-Za-z0-9_~@#$]+

但是这样写并无法排除穿插在其中的特殊字符,比如”!22A123B2!##@$#@!”,这三个感叹号会分割匹配结果,并没有排除掉感叹号情况。

此时需要通过正向预查表达式(?=exp),它断言自身出现的位置的后面能匹配表达式exp。
即必须包含exp,只要将大写字母表达式写在exp即可。

匹配单个大写字符:

1
[A-Z]

匹配任意字符多次,包含大写字符:

1
.*[A-Z]

于是包含大写的正向预查表达式出来了:

1
(?=.*[A-Z])

但是在正则表达式测试网站测试,这个表达式并不能匹配出任何字符,原因他只是个断言,所以最终得出的包含大写字母的表达式如下:

1
^(?=.*?[A-Z])[A-Za-z0-9_~@#$]+$

类似可分别得出包含小写字母、数字、特殊字符的表达式。

长度至少为8位,正则表达式:

1
{8,}

但是由于第一条规则的正则表达式已经进行了拆解,所以通过Java代码实现。

不能包含3位以上相同字符:

1
([0-9a-zA-Z.~!@$_])\1{2}

“\1”代表第一个圆括号表达式的值,”{2}”代表至少匹配两次。

为了加速匹配还可以一开始进行字符集判断,含有其他特殊字符的就不进行下述的排查:

1
^[A-Za-z0-9.~!@$_]+$

于是密码匹配规则伪代码出来了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public int passwordMatching(String password, String account) {
// 1.判断是否包含其他不合法字符^[A-Za-z0-9.~!@$_]+$

// 2.判断长度至少为8位

// 3.判断不能包含自身账号

// 4.判断新密码必须包含大写字母、小写字母、数字、特殊字符任意3种组合
int level = 0;
for (String regex : regexArray) {
if (Pattern.matches(regex, str)) {
level++;
}
}
int PASS_LEVEL = 3;
return level >= PASS_LEVEL? SUCCEED : FAILED;
}

// 5.不能是最近5次使用密码这个客户端不好处理,由服务端判断。

Done.

0%