0

I have built a regular expression for password policy match, but it is not working as expected

/((?=.\d)(?=.[a-z])(?=.[A-Z])(?=.[@#\$%!])(?!(.)*\1{2,}).{6,20})/

Password must satisfy below rules -> must have 1 digit -> must have 1 upper case letter -> must have 1 lower case letter -> must have 1 special character from given list -> minimum 6 character long -> maximum 20 character long -> Not more than 2 identical characters`

So it matches

aDm!n1, Adw1n@

but it must not match below aaaD!n1, teSt@111

I have searched for this regular expression and found "(?!(.)*\1{2,})" is not working properly

I am not getting why it is not working even though it has lookahead negative assertion.

Thanks in advance

5
  • "Not more than 2 identical characters" --- this is a stupid rule. "maximum 20 character long" --- this is another stupid rule. Commented Nov 28, 2014 at 6:39
  • Don't go for all rules, I have added it for simplicity Commented Nov 28, 2014 at 6:41
  • So you intentionally added meaningful (and insecure) requirements? That's weird. Commented Nov 28, 2014 at 6:42
  • How it is insecure? there is no maximum character limit actually. It is to stop user entering passwords like [email protected] Commented Nov 28, 2014 at 6:44
  • "there is no maximum character limit actually" --- .{6,20} --- 1. there is 2. It reduces the space of possible passwords significantly. Do you seriously think this is ziMsp8DyQk3MXK3CDNOocsDOHHHH an insecure password? Commented Nov 28, 2014 at 6:44

2 Answers 2

1

You must need to provide start and end anchors.

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#\$%\!])(?!.*(.).*\1.*\1).{6,20}$

DEMO

To match the strings which isn't contain more than two duplicate characters, you need to use a negative lookahead like (?!.*(.).*\1.*\1) which asserts that the string we are going to match wouldn't contain not more than two duplicate characters.

  • (?!) Negative lookahead which checks if there isn't
  • .* Any character zero or more times.
  • (.) A single character was captured.
  • .* Any character zero or more times.
  • \1 Reference to the group index 1. That is, it refers to the character which are already captured by group 1.
  • .* Any character zero or more times.
  • \1 Back-referencing to the character which was present inside the group index 1.

Code:

> var re = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#\$%\!])(?!.*(.).*\1.*\1).{6,20}$/;
undefined
> re.test('aDm!n1')
true
> re.test('Adw1n@')
true
> re.test('tetSt@11')
false
Sign up to request clarification or add additional context in comments.

5 Comments

teSt@111 this is invalid as it contains 111 thrice. But it is still validated
@user1531437 now check my regex.
Still it is not working, gives "Your pattern does not match the subject string."
could you provide the subject string? If you don't want to allow the strings like ftftT (ie, there t's upper or lower case) then use a case insensitive modifier.
It must not allow same continuous character more than twice abababab Allowed aaaabbcc Not allowed It has nothing to do with case, any character must be checcked
0
(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#\$%!])(?!.*(.).*\1.*\1).{6,20})

You need this.See demo.

http://regex101.com/r/hQ9xT1/22

Your regex was failing cos

(?!(.)*\1{2,}) will not work as it find consecutive repeated characters and not any character which is three times or more.So use (?!.*(.).*\1.*\1).

var re = /^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#\$%!])(?!.*(.).*\1.*\1).{6,20})$/gm;
var str = 'aaaD!n1\nteSt@111\naDm!n1\nAdw1n@';
var m;

while ((m = re.exec(str)) != null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.