Reputation: 807
I want to use java-script to validate following criteria for password.
a.A password of at least 8 and no more than 24 characters is required.
b.Every password must contain at least three of these four types of characters:
1.an upper case letter
2.a lower case letter
3.a number
4.a special character.
I have found this code which is really easy and hand-full but it is just checking all 4 conditions not just at-least 3 conditions out of 4.
"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&])[A-Za-z\d$@$!%*?&]{8,24}"
I will really appreciate if you help me to figure out to create javascript validation on password to full fill my above requirement.
Thank you all for your help. I have modified @Ehtesham code and achieved the functionality.
function isValidPassword(pass) {
var lowerRegex = /[a-z]/;
var upperRegex = /[A-Z]/;
var numberRegex = /[0-9]/;
var specialRegex = /[$@$!%*?&]/;
var count = 0;
if (pass.length < 8 || pass.length > 24) {
return false;
}
if (pass.match(lowerRegex)){count += 1;}
if (pass.match(upperRegex)){count += 1;}
if (pass.match(numberRegex)){count += 1;}
if (pass.match(specialRegex)){count += 1;}
if (count >= 3){
return true;
}else{
return false;
}
}
Upvotes: 1
Views: 2127
Reputation: 1
This builds on Ehtesham's answer to require 3 out of 4:
function isValidPassword(pass) {
var lowerRegex = /[a-z]/;
var upperRegex = /[A-Z]/;
var numberRegex = /[0-9]/;
var specialRegex = /[$@$!%*?&]/;
var mustBe3 = 0;
if(pass.length < 9 || pass.length > 24) { return false; }
if(pass.match(lowerRegex)) { mustBe3 ++; }
if(pass.match(upperRegex)) { mustBe3 ++; }
if(pass.match(numberRegex)) { mustBe3 ++; }
if(pass.match(specialRegex)){ mustBe3 ++; }
// for testing ...
if(window.console) console.log('pass: '+pass+' mustBe3: '+mustBe3);
if( mustBe3 >= 3 ) { return true; }
return false;
}
Upvotes: 0
Reputation: 2985
In javascript you can use following simple function.
function isValidPassword(pass) {
var lowerRegex = /[a-z]/;
var upperRegex = /[A-Z]/;
var numberRegex = /[0-9]/;
var specialRegex = /[$@$!%*?&]/;
if (pass.length < 8 || pass.length > 24) {
return false;
}
if (pass.match(lowerRegex) && pass.match(upperRegex) &&
pass.match(numberRegex) && pass.match(specialRegex)) {
return true;
}
return false;
}
Upvotes: 1
Reputation: 20163
Please consider bookmarking the Stack Overflow Regular Expressions FAQ for future reference. There is a password validation entry under
"Common validation tasks > Internet"
That said, this seems like a pretty easy task if you break it up, as others have suggested. Mashing up all those requirements into a single regex, although an interesting exercise, is overkill in my opinion.
(This is Java, but there are equivalent concepts in JavaScript.)
public bolean isPasswordValid(String password) {
if(!length in bounds) {
return false;
}
boolean hasUpper = Pattern.compile("[a-z]").find(password);
boolean hasLower = Pattern.compile("[A-Z]").find(password);
boolean hasDigit = Pattern.compile("[0-9]").find(password);
boolean hasSpecialChar = Pattern.compile("...NOT SURE OF THIS ONE...").find(password);
int types = (hasUpper ? 1 : 0) + (hasLower ? 1 : 0) +
(hasDigit ? 1 : 0) + (hasSpecialChar ? 1 : 0);
return (types >= 3);
}
And if this is a function that will be used rapid fire, then you'll likely want to pre-compile and store those Matchers.
Upvotes: 2
Reputation: 20909
The regex you provided is made out of 5 major parts:
[A-Za-z\d$@$!%*?&]{8,24}
(?=.*[a-z])
(?=.*[A-Z])
(?=.*\d)
(?=.*[$@$!%*?&])
Now, you only want to apply 3 out of the 4 positive lookaheads. Since lookaheads are non-consuming matches, the cursor of the regex-engine will remain unchanged, as the matching is going on. (Using positive Lookaheads this way is often used to generate AND
-Patterns)
So, you now have 4 conditions and you want that only 3 of them are matched. As described, it would be easy to use independent expressions and check if 3 apply. However, some native features (for instance jsf's f:validateRegex
) only work with a single pattern.
Regular Expressions are supporting OR
in a native way: |
- hence to turn your expression 1 AND 2 AND 3 AND 4
into a minimum requirement of matching 3 of them, you could use an expression like (1 AND 2 AND 3) OR (1 AND 2 AND 4) OR (1 AND 3 AND 4) OR (2 AND 3 AND 4)
, which would cover all usecases required:
1 2 3 4
1 1 1 0
1 1 0 1
1 0 1 1
0 1 1 1
So, to match all this within a single pattern, just rearange your lookaheads as required:
^(?:(?=.*[a-z])(?=.*[A-Z])(?=.*\d)|(?=.*[a-z])(?=.*[A-Z])(?=.*[$@$!%*?&])|(?=.*[a-z])(?=.*\d)(?=.*[$@$!%*?&])|(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&]))[A-Za-z\d$@$!%*?&]{8,24}$
Drilldown:
^(?: - non matching group
(?=.*[a-z])(?=.*[A-Z])(?=.*\d) - one lower, one upper, one number
| - or
(?=.*[a-z])(?=.*[A-Z])(?=.*[$@$!%*?&]) - one lower, one upper, one special
| - or
(?=.*[a-z])(?=.*\d)(?=.*[$@$!%*?&]) - one lower, one number, one special
| - or
(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&]) - one upper, one number, one special
)
[A-Za-z\d$@$!%*?&]{8,24}$ - 8 to 24 chars.
(Debuggex is using javascript)
^(?:(?=.*[a-z])(?=.*[A-Z])(?=.*\d)|(?=.*[a-z])(?=.*[A-Z])(?=.*[$@$!%*?&])|(?=.*[a-z])(?=.*\d)(?=.*[$@$!%*?&])|(?=.*[A-Z])(?=.*\d)(?=.*[$@$!%*?&]))[A-Za-z\d$@$!%*?&]{8,24}$
Upvotes: 4