Regex that validates Active Directory default pass

2020-02-12 07:28发布

I have a list of passwords that I need to examine and determine if they meet the default 3 of 4 rule for AD.

Rule is contain 3 of the 4 following requirements: lower case character (a-z) upper case character (A-Z) numeric (0-9) special character ( !@#$%^&*()_+= )

I am still learning Regex. I know how to select only those that meet any one character case, but I am not sure how to do 3 of 4.

As a side note, the AD Complexity has two more subtleties that are important (but out of scope of the original question).

It is really 3 of 5. The fifth is Unicode character. Be nice to update the Regex with that.

The other is you cannot have the sAMAccountName value in whole in the password (case insensitive), nor if you split the displayName value into tokens split upon space, comma, dash, underscore, pound, pipe and something else those tokens (3 chars and longer) cannot be in whole in the password, case insensitive.

4条回答
萌系小妹纸
2楼-- · 2020-02-12 08:16

You will have to build up the regular expression like this:

rule = [ "[a-z]", "[A-Z]", "[0-9]", "[!@#$%\^\&\(\)\+=]" ]

regex = ""
first = true
for a in 0..3:
  for b in 0..3:
    if a == b: continue
    for c in 0..3:
      if a == c or b == c: continue
      if not first:
        regex += "|"
      regex += "(" + rule[a] + ".*" + rule[b] + ".*" + rule[c] + ")"
      first = false

I'm not sure if I escaped the special characters correctly. It's kind of dependant on the language/toolkit you're using.

查看更多
一夜七次
3楼-- · 2020-02-12 08:22

I edited the @saul-dolgin answer to exactly match with the valid charset specified in the question (not a a non-alfanumeric character [^A-Za-z0-9]):

(?=^[A-Za-z\d!@#\$%\^&\*\(\)_\+=]{8,20}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[!@#\$%\^&\*\(\)_\+=])(?=.*[a-z])|(?=.*[!@#\$%\^&\*\(\)_\+=])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[!@#\$%\^&\*\(\)_\+=]))^.*

Microsoft forces passwords to have only characters from their list. I also changed the Maximum lenght to 20.

查看更多
ら.Afraid
4楼-- · 2020-02-12 08:27

Does it have to be all one big regex? You could do 4 regexes, each checking one thing and then make sure 3 of the 4 are matches. That would be easier, less error prone and more maintainable.

查看更多
Explosion°爆炸
5楼-- · 2020-02-12 08:34

If you really want one big regex it would be something like this:

(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*

Note that it also enforces password length to be between 8 and 255 characters. You can change the "{8,255}" portion in the first section to adjust the length requirements. It is also worth noting that this is working for me in a standard ASP.NET RegularExpressionValidator control.

Matches: "Passw0rd" "passW@rd" "1B2a345@#$%"

Non-Matches: "123123123" "Password" "asdf&"

Source (Matthew Hazzard via RegExLib.com)

查看更多
登录 后发表回答