开发者

strong password regex

OK so I have a mental block when it comes to regex - but I was told to come up with a regex expression that met these conditions:

  • must be at least 8 characters (easy!)
  • must have characters from at least 3 of the 4 different character types - upper case, lower case, digits, symbols (ok)
  • must have at least 5 different characters
  • must not have a long sequence of the same character type (eg. asdnme would be considered bad as its a long sequence of lower case)
(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9\s])(?=.*[a-z])|(?=.*[^A-Za-z0-9\s])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s]))

This regex expression satisfies 1 and 2. But I am struggling to find examples for 3 and 4.

If any regex enthusiasts could help me - it would be appreciated. :)

Note: I would prefer not to use Regex - this is me asking anyone if it's possible to check for the 3rd and 4th condition using regex? And please don't downvote me for the belief that regex is the only solution. I don't believe it is - our achitect decided the least effort would be involved in using regex to solve this issue.

Personally I think this level of password security is going to make the system unusable!!! But maybe I don't care enough about password security :)

Note: We're trying to make use of the Microsoft ASPNET Membership - regex expression. Which is why I thought it needed to be a single expression. I get that it's horrible to try to read/understand.

If anyone can provide individual regex expressions for - must have at least 5 different characters - must not have a long sequence of the same character type (eg. asdnme would be considered bad as its a long sequence of lower case) - assume 5 sequence is too long..

Or c# code /javascript ? Although this is specific to one particular client - we don't want it blanked applied to all clients. Which is probably why the architect wanted a nice regex expression that you could just slot in at deployment time. :(

Found someone else's example that works in .NET

^(?!.*(.)\1{2})((?[A-Z])|(?[a-z])|(?\d)|(?[^A-Za-z\d])){8,}(?(Upper)(?(Lower)(?(Numeric)|(?(NonAlphaNumeric)|(?!)))|(?(Numeric)(?(NonAlphaNumeric)|(?!))|(?!)))|(?(Lower)(?(Numeric)(?(NonAlphaNumeric)|(?!))|(?!))|(?!)))$

Unfortunately it meets these conditions:

  • Must have a minimum length of 8 characters

  • Must contain characters from three of the four following types:

  • English upper-case characters (A - Z)

  • English lower-case characters (a - z)

  • Numerical digits (0 - 9)

  • Non-alphanumeric characters

  • No character can be repeated 3 or more times in a row, e.g. BB (letter B twice) is OK, but BBB (letter B 3 times) is NOT OK.

But it doesn't detect that at least 5 different characters are used :(

Nevermind - the answer below开发者_如何转开发 seems to work. Only thing is that it appears to allow 4 different characters rather than requiring 5?

I have tweaked it to be: ^(?=.{8,})(?:(?=.\d)(?=.[A-Z])(?=.[a-z])|(?=.\d)(?=.[^A-Za-z0-9\s])(?=.[a-z])|(?=.[^A-Za-z0-9\s])(?=.[A-Z])(?=.[a-z])|(?=.\d)(?=.[A-Z])(?=.[^A-Za-z0-9\s]))(?=(.)(?>.?(?!\1})(.))(?>.?(?!\1}|\2)(.))(?>.?(?!\1|\2|\3)(.))(?>.?(?!\1|\2|\3|\4)(.))(?>.?(?!\1|\2|\3|\4|\5).))(?!.?\d{4})(?!.?[a-z]{4})(?!.?[A-Z]{4})(?!.*?[^A-Za-z0-9\s]{4})

Here's hoping we never have to touch it again ;) With more time if this crops up again I'll push the code option I think :)

Edit: Discovered that the string isn't quite right. It's not passing "!tt23yyy" without having to add another digit or special character. So have canned the regex idea and am going with the code option. It's just too hard to debug regex issues if you don't comprehend regex :) (understandably so)


Here is a PCRE/Perl regex that would do all that:

/
^ # anchor it

# must be at least 8 characters
(?=.{8,})

# must have characters from at least 3 of the 4 different character types
(?: 
  (?=.*\d)(?=.*[A-Z])(?=.*[a-z])
| (?=.*\d)(?=.*[^A-Za-z0-9\s])(?=.*[a-z])
| (?=.*[^A-Za-z0-9\s])(?=.*[A-Z])(?=.*[a-z])
| (?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9\s])
)

# at least 5 different chars
(?=
                       (.)
  (?>.*?(?!\1})        (.))
  (?>.*?(?!\1}|\2)     (.)) 
  (?>.*?(?!\1|\2|\3)   (.)) 
  (?>.*?(?!\1|\2|\3|\4) . )
)

# no long sequence of the same character type (if long is 3)
(?!.*?\d{3})
(?!.*?[a-z]{3})
(?!.*?[A-Z]{3})
(?!.*?[^A-Za-z0-9\s]{3})

/xs

Not tested so could have missed something. Enjoy. ;-)

If you are really going to be using that (on longer strings), you might want to add some (more) atomic grouping (?>foo) (or the like) to prevent exponential backtracking.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜