Regular expression to enforce complex passwords, m

2019-01-01 13:46发布

I have the following criteria for creating a regular expression for a password that conforms to the following rules:

  1. The password must be 8 characters long (this I can do :-)).

The password must then contain characters from at least 3 of the following 4 rules:

  1. Upper case
  2. Lower case
  3. Numbers
  4. Non-alpha numeric

I can make the expression match ALL of those rules with the following expression:

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

But I am struggling with how to do this in such a way that it only needs to solve any 3 of the 4 rules.

Can anyone help me out with this?

标签: regex
4条回答
永恒的永恒
2楼-- · 2019-01-01 13:56

You could write a really sophisticated regex to do that. Instead, I’d suggest writing four distinct regexes, one for each rule, and testing them one by one, counting how many of them matched. If three out of four did, accept the password.

查看更多
裙下三千臣
3楼-- · 2019-01-01 14:05

Don't use one regex to check it then.

if (password.length < 8)
  alert("bad password");
var hasUpperCase = /[A-Z]/.test(password);
var hasLowerCase = /[a-z]/.test(password);
var hasNumbers = /\d/.test(password);
var hasNonalphas = /\W/.test(password);
if (hasUpperCase + hasLowerCase + hasNumbers + hasNonalphas < 3)
  alert("bad password");

If you must use a single regex:

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

This regex is not optimized for efficiency. It is constructed by A·B·C + A·B·D + A·C·D + B·C·D with some factorization. Breakdown:

^
(?:
    (?=.*[a-z])       # 1. there is a lower-case letter ahead,
    (?:               #    and
        (?=.*[A-Z])   #     1.a.i) there is also an upper-case letter, and
        (?=.*[\d\W])  #     1.a.ii) a number (\d) or symbol (\W),
    |                 #    or
        (?=.*\W)      #     1.b.i) there is a symbol, and
        (?=.*\d)      #     1.b.ii) a number ahead
    )
|                     # OR
    (?=.*\W)          # 2.a) there is a symbol, and
    (?=.*[A-Z])       # 2.b) an upper-case letter, and
    (?=.*\d)          # 2.c) a number ahead.
)
.{8,}                 # the password must be at least 8 characters long.
$
查看更多
时光乱了年华
4楼-- · 2019-01-01 14:06

You can use the following Regex:

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

With a password minimum length of 8 and max length 32 you can use the following Regex:

(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,32}$)?(^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).{8,32}$)?(^(?=.*\d)(?=.*[A-Z])(?=.*[@#$%^&+=]).{8,32}$)?(^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).{8,32}$)?
查看更多
临风纵饮
5楼-- · 2019-01-01 14:11

Id suggest doing the checks seperately, and then just totalling up how many match.

(I'd also not use a regex in any of them, but thats just my personal POV - namely that they hinder readability and are generally write-once code)

查看更多
登录 后发表回答