在用户注册业务场景中,一般而言的用户密码强度:密码至少8个字符,包括1个大写字母,1个小写字母和1个数字或特殊字符。本文原本转载来自css88的一篇整理,但是其内容只是简单说明了几种验证密码强度正则的写法,比如说 /^(?=.*\d)(?=.*[a-zA-Z]).{6,20}$/
,这里用了「先行断言」,之前自己对此理解不太准确,本文就是附带讲解这个概念来一步一步说明密码强度正则的写法。
先行断言
先行断言(Positive look-ahead)的语法形式为 x(?=y)
,意思就是 x 只有在 y 前面才匹配,并且 y 不会被计入返回结果。
如果要匹配一个 70% 中的数字,就可以写成 /\d+(?=%)/
。
先行断言很容易让人误解,比如说上面举例的密码强度表达式(/^(?=.*\d)(?=.*[a-zA-Z]).{6,20}$/
)中的先行断言前面并没有任何字符,它其实只是匹配某些位置不占用字符,所以匹配返回的内容是不包括先行断言内的内容的。
下面使用 JavaScript 具体说明:
1
| var res = /(?=\d)[a-z]/.test("1h")
|
那么res
的返回结果是?肯定有人说是 true
但是正确结果为 false
。
接下来来分析一下,想象一个指针在字符串 1h
上移动,那么根据上面例子的正则,指针会在 1h
之前,用下划线指代指针的话,指针的位置就是 _1h
的,但是 (?=\d)[a-z]
要求后面的字符是不是数字而是小写字母,所以就匹配不了。
那么,我们稍微修改一下,现在就匹配了。也就是说断言不消耗字符,如果找不到断言就不匹配。
1
| /(?=\d)\d[a-z]/.test("1h")
|
那么再说明密码强度的正则就简单了。
1
| /^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{6,}$/
|
在断言中加入 .
代表任意字符,那么就是匹配整个密码字符串。
密码强度库
除了正则之外,还有一个业界通用的密码强度库 Dropbox 的 zxcvbn。
库名字很好记就是键盘字符第三排的字母,另外根据统计取这样密码的用户很多。
zxcvbn 覆盖了所有主流的语言,包括 JS PHP Python 等,前端也可以直接引入,不过我并不推荐,因为包太大了,足有 800K。如果前端使用的话,最好还是使用正则。