Sunil
Sunil

Reputation: 521

Password check using regex in Java

My application has a feature to check password. I need to get this scenario:

password length 10 ~ 32 .

It has to be a combination of either:

Current code in application:

private boolean isSpecialMixedText(String password)
{
    String number = "[0-9]";
    String english = "[a-zA-Z]";
    String special = "[!@#\\$%^&*()~`\\-=_+\\[\\]{}|:\\\";',\\./<>?£¥\\\\]";

    Pattern numberPattern = Pattern.compile(number);
    Matcher numberMatcher = numberPattern.matcher(password); 

    Pattern englishPattern = Pattern.compile(english);
    Matcher englishMatcher = englishPattern.matcher(password);

    Pattern specialPattern = Pattern.compile(special);
    Matcher specialMatcher = specialPattern.matcher(password);
    return numberMatcher.find() && englishMatcher.find() || specialMatcher.find();
}

Please help me get the combination working

Upvotes: 3

Views: 187

Answers (2)

m.cekiera
m.cekiera

Reputation: 5395

In my opinion your logic is wrong because you look for combination (so only these characters allowed) of: characters and numbers OR characters and special characters OR numbers and special characters. However with pair of matches like: [0-9] and [a-zA-Z] you are actually looking for a String with some digits and some letter, but it could be also 123ABC#$%#$%$#%#$ (because it has letters and digits).

What you need is something to check, if given string is composed ONLY of of allowed combination of characters. I think you can use one regex here (not too elegant, but effective) like:

^(?:((?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32})|((?=.*[-!@#\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[0-9].*)[0-9-!@#\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32})|((?=.*[-!@#\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\].*)(?=.*[A-Za-z].*)[-A-Za-z!@#\\$%^&*()~`\=_+\[\]{}|:\";',.\/<>?£¥\\]{10,32}))$

DEMO - it show valid and invalid matches.

This is quite long regex, but mainly because of you special character class. This regular expression is composed of three parts with similar structure:

positive lookagead for required characters + character class of allowed characters

On an example:

(?=.*[A-Za-z].*)(?=.*[0-9].*)[A-Za-z0-9]{10,32}

means that string need to have:

  • (?=.*[A-Za-z].*) - at least one letter (positive lookahead for letter which could be surrounded by other characters),
  • (?=.*[0-9].*) - at least one number (positive lookahead for digit which could be surrounded by other characters)
  • [A-Za-z0-9]{10,32} - from 10 to 32 letters or digits, in effect, the given password need to have 10 to 32 characters, but both letters and digits, proportion is not important.

Whats more, the ^ at beginning and $ in the end ensure that the whole examined string has such composition.

Also I would agree with others, it is not best idea to restrict allowed character in password like that, but it is your decision.

Upvotes: 1

Stephen C
Stephen C

Reputation: 718826

Actually, the regexes look fine. The problem is in this statement:

return numberMatcher.find() && englishMatcher.find() || 
       specialMatcher.find();

It actually needs to be something like this:

boolean n = numberMatcher.find();
boolean e = englishMatcher.find();
boolean s = specialMatcher.find();
return (n && e) || (n && s) || (e && s);

And I agree with @adelphus' comment. Your rules for deciding what passwords are acceptable are very English-language-centric.

Upvotes: 2

Related Questions