Kerby82
Kerby82

Reputation: 5146

Regexp Java for password validation

I'm creating a regexp for password validation to be used in a Java application as a configuration parameter.

The regexp is:

^.*(?=.{8,})(?=..*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

The password policy is:

I’m missing just point 5. I'm not able to have the regexp check for space, tab, carriage return, etc.

Could anyone help me?

Upvotes: 121

Views: 193558

Answers (17)

user3816638
user3816638

Reputation: 53

A more general answer which accepts all the special characters including _ would be slightly different:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\W|\_])(?=\S+$).{8,}$

The difference (?=.*[\W|\_]) translates to "at least one of all the special characters including the underscore".

Upvotes: 0

surfealokesea
surfealokesea

Reputation: 5116

Thanks for all answers, based on all them but extending sphecial characters:

@SuppressWarnings({"regexp", "RegExpUnexpectedAnchor", "RegExpRedundantEscape"})
String PASSWORD_SPECIAL_CHARS = "@#$%^`<>&+=\"!ºª·#~%&'¿¡€,:;*/+-.=_\\[\\]\\(\\)\\|\\_\\?\\\\";
int PASSWORD_MIN_SIZE = 8;
String PASSWORD_REGEXP = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[" + PASSWORD_SPECIAL_CHARS + "])(?=\\S+$).{"+PASSWORD_MIN_SIZE+",}$";

Unit tested:

enter image description here

Upvotes: 5

Ankit Kumar Rajpoot
Ankit Kumar Rajpoot

Reputation: 5600

RegEx is -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. at least 8 digits {8,}
  2. at least one number (?=.*\d)
  3. at least one lowercase (?=.*[a-z])
  4. at least one uppercase (?=.*[A-Z])
  5. at least one special character (?=.*[@#$%^&+=])
  6. No space [^\s]

Upvotes: 0

Sample code block for strong password:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. at least 6 digits
  2. up to 18 digits
  3. one number
  4. one lowercase
  5. one uppercase
  6. can contain all special characters

Upvotes: 0

Use Passay library which is powerful api.

Upvotes: 1

RANAJEET BARIK
RANAJEET BARIK

Reputation: 185

Also You Can Do like This.

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}

Upvotes: 1

Fausto70
Fausto70

Reputation: 551

Java Method ready for you, with parameters

Just copy and paste and set your desired parameters.

If you don't want a module, just comment it or add an "if" as done by me for special char

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        

Upvotes: 1

Ansu
Ansu

Reputation: 41

This one checks for every special character :

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$

Upvotes: 1

Naresh Babu
Naresh Babu

Reputation: 1

String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

Explanation:

  1. First set the password as a string and create integer set o.
  2. Then check the each and every char by for loop.
  3. If it finds number in the string then the n add 5. Then jump to the next for loop. Character.isDigit(s.charAt(i))
  4. This loop check any alphabets placed in the string. If its find then add one more 5 in n. Character.isLetter(s.charAt(i))
  5. Now check the integer n by the way of if condition. If n=10 is true given string is alphanumeric else its not.

Upvotes: 0

ibrahem shabban
ibrahem shabban

Reputation: 1101

easy one

("^ (?=.* [0-9]) (?=.* [a-z]) (?=.* [A-Z]) (?=.* [\\W_])[\\S]{8,10}$")

  1. (?= anything ) ->means positive looks forward in all input string and make sure for this condition is written .sample(?=.*[0-9])-> means ensure one digit number is written in the all string.if not written return false .

  2. (?! anything ) ->(vise versa) means negative looks forward if condition is written return false.

    close meaning ^(condition)(condition)(condition)(condition)[\S]{8,10}$

Upvotes: 0

Demetrios Christopher
Demetrios Christopher

Reputation: 405

For anyone interested in minimum requirements for each type of character, I would suggest making the following extension over Tomalak's accepted answer:

^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

Notice that this is a formatting string and not the final regex pattern. Just substitute %d with the minimum required occurrences for: digits, lowercase, uppercase, non-digit/character, and entire password (respectively). Maximum occurrences are unlikely (unless you want a max of 0, effectively rejecting any such characters) but those could be easily added as well. Notice the extra grouping around each type so that the min/max constraints allow for non-consecutive matches. This worked wonders for a system where we could centrally configure how many of each type of character we required and then have the website as well as two different mobile platforms fetch that information in order to construct the regex pattern based on the above formatting string.

Upvotes: 1

agiles
agiles

Reputation: 1721

simple example using regex

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "aaZZa44@"; 
      String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
      System.out.println(passwd.matches(pattern));
   }
}

Explanations:

  • (?=.*[0-9]) a digit must occur at least once
  • (?=.*[a-z]) a lower case letter must occur at least once
  • (?=.*[A-Z]) an upper case letter must occur at least once
  • (?=.*[@#$%^&+=]) a special character must occur at least once
  • (?=\\S+$) no whitespace allowed in the entire string
  • .{8,} at least 8 characters

Upvotes: 63

Martin Rauscher
Martin Rauscher

Reputation: 1806

You should not use overly complex Regex (if you can avoid them) because they are

  • hard to read (at least for everyone but yourself)
  • hard to extend
  • hard to debug

Although there might be a small performance overhead in using many small regular expressions, the points above outweight it easily.

I would implement like this:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}

Upvotes: 13

Jan Goyvaerts
Jan Goyvaerts

Reputation: 21999

All the previously given answers use the same (correct) technique to use a separate lookahead for each requirement. But they contain a couple of inefficiencies and a potentially massive bug, depending on the back end that will actually use the password.

I'll start with the regex from the accepted answer:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

First of all, since Java supports \A and \z I prefer to use those to make sure the entire string is validated, independently of Pattern.MULTILINE. This doesn't affect performance, but avoids mistakes when regexes are recycled.

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z

Checking that the password does not contain whitespace and checking its minimum length can be done in a single pass by using the all at once by putting variable quantifier {8,} on the shorthand \S that limits the allowed characters:

\A(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])\S{8,}\z

If the provided password does contain a space, all the checks will be done, only to have the final check fail on the space. This can be avoided by replacing all the dots with \S:

\A(?=\S*[0-9])(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[@#$%^&+=])\S{8,}\z

The dot should only be used if you really want to allow any character. Otherwise, use a (negated) character class to limit your regex to only those characters that are really permitted. Though it makes little difference in this case, not using the dot when something else is more appropriate is a very good habit. I see far too many cases of catastrophic backtracking because the developer was too lazy to use something more appropriate than the dot.

Since there's a good chance the initial tests will find an appropriate character in the first half of the password, a lazy quantifier can be more efficient:

\A(?=\S*?[0-9])(?=\S*?[a-z])(?=\S*?[A-Z])(?=\S*?[@#$%^&+=])\S{8,}\z

But now for the really important issue: none of the answers mentions the fact that the original question seems to be written by somebody who thinks in ASCII. But in Java strings are Unicode. Are non-ASCII characters allowed in passwords? If they are, are only ASCII spaces disallowed, or should all Unicode whitespace be excluded.

By default \s matches only ASCII whitespace, so its inverse \S matches all Unicode characters (whitespace or not) and all non-whitespace ASCII characters. If Unicode characters are allowed but Unicode spaces are not, the UNICODE_CHARACTER_CLASS flag can be specified to make \S exclude Unicode whitespace. If Unicode characters are not allowed, then [\x21-\x7E] can be used instead of \S to match all ASCII characters that are not a space or a control character.

Which brings us to the next potential issue: do we want to allow control characters? The first step in writing a proper regex is to exactly specify what you want to match and what you don't. The only 100% technically correct answer is that the password specification in the question is ambiguous because it does not state whether certain ranges of characters like control characters or non-ASCII characters are permitted or not.

Upvotes: 14

shA.t
shA.t

Reputation: 16958

I think this can do it also (as a simpler mode):

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])[^\s]{8,}$

[Regex Demo]

Upvotes: 0

Andrew
Andrew

Reputation: 11

Password Requirement :

  • Password should be at least eight (8) characters in length where the system can support it.
  • Passwords must include characters from at least two (2) of these groupings: alpha, numeric, and special characters.

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$
    

I tested it and it works

Upvotes: 1

Tomalak
Tomalak

Reputation: 338228

Try this:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\S+$).{8,}$

Explanation:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

It's easy to add, modify or remove individual rules, since every rule is an independent "module".

The (?=.*[xyz]) construct eats the entire string (.*) and backtracks to the first occurrence where [xyz] can match. It succeeds if [xyz] is found, it fails otherwise.

The alternative would be using a reluctant qualifier: (?=.*?[xyz]). For a password check, this will hardly make any difference, for much longer strings it could be the more efficient variant.

The most efficient variant (but hardest to read and maintain, therefore the most error-prone) would be (?=[^xyz]*[xyz]), of course. For a regex of this length and for this purpose, I would dis-recommend doing it that way, as it has no real benefits.

Upvotes: 363

Related Questions