I\'m a Regex newbie, and so far have only used it for simple things, like \"must be a number or letter\". Now I have to do something a bit more complex.
I need to u
The best way to do this is by checking each condition separately. Performance will suffer if you try to fit all conditional criteria into one expression (see the accepted answer). I also highly recommend against limiting the length of the password to 16 chars — this is extremely insecure for modern standards. Try something more like 64 chars, or even better, 128 — assuming your hashing architecture can handle the load.
You also didn't specify a language, but this is one way to do it in JavaScript:
var pws = [
"%5abCdefg",
"&5ab",
"%5abCdef",
"5Bcdwefg",
"BCADLKJSDSDFlk"
];
function pwCheck(pw) {
var criteria = 0;
if (pw.toUpperCase() != pw) {
// has lower case letters
criteria++;
}
if (pw.toLowerCase() != pw) {
// has upper case letters
criteria++;
}
if (/^[a-zA-Z0-9]*$/.test(pw) === false) {
// has special characters
criteria++;
}
if (/\d/.test(pw) === true) {
// has numbers
criteria++;
}
// returns true if 3 or more criteria was met and length is appropriate
return (criteria >= 3 && pw.length >= 8 && pw.length <= 16);
}
pws.forEach(function(pw) {
console.log(pw + ": " + pwCheck(pw).toString());
});
Not sure if its a iOS thing, the regex with "d" for digits [0-9] wasn't working as expected, example String that had issues = "AAAAAA1$"
The fix below works fine in Objective-C and Swift 3
^((?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])|(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[^a-zA-Z0-9])|(?=.*?[A-Z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])|(?=.*?[a-z])(?=.*?[0-9])(?=.*?[^a-zA-Z0-9])).{8,16}$
The correct way to do this is to check all of the five conditions separately. However, I assume there is a reason you want a regex, here you go:
/^((?=.*[A-Z])(?=.*[a-z])(?=.*\d)|(?=.*[a-z])(?=.*\d)(?=.*[\$\%\&])|(?=.*[A-Z])(?=.*\d)(?=.*[\$\%\&])|(?=.*[A-Z])(?=.*[a-z])(?=.*[\$\%\&])).{8,16}$/
Explanation:
^$
.{n,m}
matches between n
and m
characters (8 and 16 in our case).(?=.*X)
, where X
is the thing you want to check. For example, if you want to make sure the string contains a lowercase letter you can do (?=.*[a-z])
.X
, Y
and Z
, but without actually matching them, you can use the previous recipe by appending the three lookaheads (?=.*X)(?=.*Y)(?=.*Z)
|
(or) - cCD|cDS|CDS|CcS
(c
= lowercase letter, C
= capital letter, D
= digit, S
= special)See it in action