Reputation: 1371
I have a password rule that needs to satisfy those condition below:
At least 2 out of the following: - At least 1 lowercase character - At least 1 uppercase character - At least 2 (numbers AND special characters)
I build my regex like this below:
String oneLowercaseCharacter = ".*[a-z].*";
String oneUppercaseCharacter = ".*[A-Z].*";
String oneNumber = ".*\\d.*";
String oneSpecialCharacter = ".*[^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
String threeNumbersAndCharacters = ".*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*[0-9\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
And then I build the function like this below:
if ((Pattern.compile(oneLowercaseCharacter).matcher(s).find() && Pattern.compile(oneUppercaseCharacter).matcher(s).find())
|| (Pattern.compile(oneLowercaseCharacter).matcher(s).find()
&& Pattern.compile(oneSpecialCharacter).matcher(s).find()
&& Pattern.compile(oneNumber).matcher(s).find()
&& Pattern.compile(threeNumbersAndCharacters).matcher(s).find())
|| (Pattern.compile(oneUppercaseCharacter).matcher(s).find()
&& Pattern.compile(oneSpecialCharacter).matcher(s).find()
&& Pattern.compile(oneNumber).matcher(s).find()
&& Pattern.compile(threeNumbersAndCharacters).matcher(s).find())) {
//Do my stuff here
}
However, it does not work as expected. Not really sure why but if I test with different passwords, results show like this:
qwerty123 true (not expected)
qwerty!@# false
qwerty12. true
Qwerty123 true
Qwerty12. true
Anyone has any idea where I missed?
Note: I search around stackoverflow already and look elsewhere already so that I came up with the above code, however could not go further.
Upvotes: 1
Views: 1921
Reputation: 56666
The problem is in this line:
String oneSpecialCharacter = ".*[^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
The character ^
has a special meaning ("not") when it is used in the first position inside []
.
This is why you need to escape it.
String oneSpecialCharacter = ".*[\\^\\`\\~\\<\\,\\>\\\"\\'\\}\\{\\]\\[\\|\\)\\(\\;\\&\\*\\$\\%\\#\\@\\!\\:\\.\\/\\?\\\\\\+\\=\\-\\_\\ ].*";
Now your result should looks like this:
qwerty123 -> false
qwerty!@# -> false
qwerty12. -> true
Qwerty123 -> true
Qwerty12. -> true
Other examples that emphasize the meaning of ^
:
// the first character cannot be a
System.out.println(Pattern.compile("[^a]bc").matcher("abc").find()); // false
// the first character cannot be x, y or z, but it can be a
System.out.println(Pattern.compile("[^xyz]bc").matcher("abc").find()); // true
// the first character can be ^ or a
System.out.println(Pattern.compile("[\\^a]bc").matcher("abc").find()); // true
// the first character can be ^, x, y or z, but not a
System.out.println(Pattern.compile("[\\^xyz]bc").matcher("abc").find()); // false
Upvotes: 1