Main Tutorials

Java regex validate password examples

Java regex password

This article shows how to use regex to validate a password in Java.

Secure Password requirements

  1. Password must contain at least one digit [0-9].
  2. Password must contain at least one lowercase Latin character [a-z].
  3. Password must contain at least one uppercase Latin character [A-Z].
  4. Password must contain at least one special character like ! @ # & ( ).
  5. Password must contain a length of at least 8 characters and a maximum of 20 characters.

Below is the regex that matches all the above requirements.


  ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–[{}]:;',?/*~$^+=<>]).{8,20}$

1. Regex password explanation

The password must contain at least one lowercase character, one uppercase character, one digit, one special character, and a length between 8 to 20. The below regex uses positive lookahead for the conditional checking.


^                                   # start of line
  (?=.*[0-9])                       # positive lookahead, digit [0-9]
  (?=.*[a-z])                       # positive lookahead, one lowercase character [a-z]
  (?=.*[A-Z])                       # positive lookahead, one uppercase character [A-Z]
  (?=.*[!@#&()–[{}]:;',?/*~$^+=<>]) # positive lookahead, one of the special character in this [..]
  .                                 # matches anything
  {8,20}                            # length at least 8 characters and maximum of 20 characters
$                                   # end of line

In regex, there is positive lookahead (?=) and negative lookahead (?!):

  • Positive lookahead (?=) ensures something followed by something else.
  • Negative lookahead (?!) ensures something NOT followed by something else.

For example, b(?=c) matches a b that is followed by a c. (positive lookahead)
For example, b(?!c) matches a b that is NOT followed by a c. (negative lookahead)

2. Regex to validate the password

Below is a Java regex example to validate a password.

PasswordValidator.java

package com.mkyong.regex.password;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PasswordValidator {

    // digit + lowercase char + uppercase char + punctuation + symbol
    private static final String PASSWORD_PATTERN =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–[{}]:;',?/*~$^+=<>]).{8,20}$";

    private static final Pattern pattern = Pattern.compile(PASSWORD_PATTERN);

    public static boolean isValid(final String password) {
        Matcher matcher = pattern.matcher(password);
        return matcher.matches();
    }

}

3. Regex password unit tests

Here are the unit tests to test a list of valid and invalid passwords.

PasswordValidatorTest.java

package com.mkyong.regex.password;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class PasswordValidatorTest {

    @ParameterizedTest(name = "#{index} - Run test with password = {0}")
    @MethodSource("validPasswordProvider")
    void test_password_regex_valid(String password) {
        assertTrue(PasswordValidator.isValid(password));
    }

    @ParameterizedTest(name = "#{index} - Run test with password = {0}")
    @MethodSource("invalidPasswordProvider")
    void test_password_regex_invalid(String password) {
        assertFalse(PasswordValidator.isValid(password));
    }

    static Stream<String> validPasswordProvider() {
        return Stream.of(
                "AAAbbbccc@123",
                "Hello world$123",
                "A!@#&()–a1",               // test punctuation part 1
                "A[{}]:;',?/*a1",           // test punctuation part 2
                "A~$^+=<>a1",               // test symbols
                "0123456789$abcdefgAB",     // test 20 chars
                "123Aa$Aa"                  // test 8 chars
        );
    }

    // At least
    // one lowercase character,
    // one uppercase character,
    // one digit,
    // one special character
    // and length between 8 to 20.
    static Stream<String> invalidPasswordProvider() {
        return Stream.of(
                "12345678",                 // invalid, only digit
                "abcdefgh",                 // invalid, only lowercase
                "ABCDEFGH",                 // invalid, only uppercase
                "abc123$$$",                // invalid, at least one uppercase
                "ABC123$$$",                // invalid, at least one lowercase
                "ABC$$$$$$",                // invalid, at least one digit
                "java REGEX 123",           // invalid, at least one special character
                "java REGEX 123 %",         // invalid, % is not in the special character group []
                "________",                 // invalid
                "--------",                 // invalid
                " ",                        // empty
                "");                        // empty
    }
}

All passed.

unit tests passed

4. FAQs

Below are some commonly asked questions:

  • Why longer password is more secured?
  • Why must mix at least one special character?

Answer:
For Latin characters, lowercase and uppercase [a-zA-Z], it consists of 52 characters; for the digits [0-9], it consists of 10 characters, a total of 62 characters.

  • If a password contains a length of 1, it consists of 62 possibilities, [a-zA-Z0-9]. It means the worst case; we need to guess 62 times to find out the correct password.
  • For a length of 2, it is 62 x 62 or 62 ^ 2 = 3,844
  • 62 ^ 3 = 238,328
  • 62 ^ 4 = 14,776,336
  • 62 ^ 5 = 916,132,832
  • 62 ^ 6 = 56,800,235,584
  • 62 ^ 7 = 3,521,614,606,208
  • 62 ^ 8 = 218,340,105,584,896
  • A longer password is more secured, because it makes attackers harder to guess the correct password. Get the idea?

If we included the special characters like punctuation ! @ # & ( ) – [ { } ] : ; ' , ? / * (18 characters) and symbols ~ $ ^ + = < > (7 characters), it will greatly increase difficulties of guesting the correct password. I’m not really sure how many special characters are there, let takes it as 25 characters (estimated).

For 62 alphanumeric characters + 25 special characters, it is a total of 87 characters.

  • 87 ^ 1 = 87
  • 87 ^ 2 = 7,569
  • 87 ^ 3 = 658,503
  • 87 ^ 4 = 57,289,761
  • 87 ^ 5 = 4,984,209,207
  • 87 ^ 6 = 433,626,201,009
  • 87 ^ 7 = 37,725,479,487,783
  • 87 ^ 8 = 3,282,116,715,437,121

Mixed with special characters will significantly increase the difficulties of guesting the correct password.

Password Hashing
Do not store the password as plaintext. It is a good practice to use slow hash like Argon2 to hash the password.

Strong Password Generator
Try this Java password generator example to generate a secure and robust password.

Download Source Code

$ git clone https://github.com/mkyong/core-java

$ cd java-regex/password

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
28 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Sawyer
9 years ago

Thanks so much for this. Any help about how to modify your regex to check for a number OR symbol? I thought (?=.*[0-9]|[!@#$%] might work, but no luck. Also, as someone else mentioned, it seems to be accepting spaces. How can I make it fail if the user enters spaces? Thanks!

Raymond Ng
11 years ago

Add (?!.*\\s) to disallow spaces in the password.

Jonas Grimsgaard
12 years ago

Thank you, you saved me ALOT of time ?

Tung Le
1 year ago

This pattern has worked perfectly until it meets this password: 1234qwER[
Open square bracket [ should be accepted but it was not. To fix this issue, add \\ before square brackets, then it should be ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\[{}\\]:;’,?/*~$^+=<>]).{8,32}$
To allow backslash as well, add \\\\ to pattern above, then it is ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\\\\\[{}\\]:;’,?/*~$^+=<>]).{8,32}$

Tung Le
1 year ago
Reply to  Tung Le

OMG even backslash in my comment was escaped :)). I pasted here the patterns I want to mentioned. Please check this one instead of above

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\[{}\\]:;',?/*~$^+=<>]).{8,32}$  \\Do not allow \

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\\\\\[{}\\]:;',?/*~$^+=<>]).{8,32}$ \\Allow \
Tung Le
1 year ago
Reply to  Tung Le

Do not allow \\:
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\\\[{}\\\\]:;’,?/*~$^+=<>]).{8,32}$
Allow \\:
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–\\\\\\\\\\\\[{}\\\\]:;’,?/*~$^+=<>]).{8,32}$

Matteo Gramigni
1 year ago

This was driving me mad… you’ve included – in the special characters, but unless you double escape it and use a normal minus char ascii 2D ( \\- ) the last part of the expression is wrong…
Copying and pasting from the web add to the issue as the minus char is (depending on the browser and/or editor i suppose) converted into a dash…

If it’s converted into a dash (from ascii 0x2D to 0x96) the expression works but ofc it ignores the minus sign
If it’s not converted, the expression will work regardless of special characters present in the password as the minus portion is interpreted as “any character between ) and _”

Matteo Gramigni
1 year ago

Ah, the two square brackets [ ] must be escaped as well…

In java code the right expression to use (double escaping slashes) should be the string:
“^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\\-_\\[{}\\]:;’,?/*~$^+=]).{8,20}$”

which is the regular expression:
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()\-_\[{}\]:;’,?/*~$^+=]).{8,20}$

Andrey
2 years ago

Hello. I took this regex:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#&()–[{}]:;’,?/*~$^+=<>])(?=\\S+\$).{8,}$
(without this symbol ‘!’. It’s important) and this pasword: xF!D!234#FFERjdjd. And my regex returned me TRUE. But the ‘!’ symbol is not in my regex. What is wrong? 

Last edited 2 years ago by Andrey
Amit Shirasao
3 years ago

Very nice. Thx.

Edwin
3 years ago

My android phone is locked,need 4 characters include 1 letter password,pls help me

Abhigyan Ghosh
6 years ago

It accepts mkyoNg123*% though. How to fix it?

Brice Vandeputte
9 years ago

5 years after, this post is always usefull (as the rest of you blog ;))
just another way here to say thanks again Mkyong to save our time ^^

Jorge Rivera
10 years ago

Why in the world would anyone want to limit maximum password length?

Manoj Sawant
9 years ago
Reply to  Jorge Rivera

As every one try to make password which is difficult to get read / understand / remember by other. If any user making very long and complicated password then, in future he/she also will not able to remember that. And if someone uses long password for Online Bank Transactions or any Online Reservation System then, may be he/she could try to insert password with all attempts. Due to which he could not get success in his transaction.
And Software Developer have to make system user friendly. Developers need to take care of network traffic also. It’s not good thing If number of users are making 3 to 4 request only for Login attempt with long password.
That’s why Password string should be short and difficult to read.

Jorge Rivera
8 years ago
Reply to  Manoj Sawant

security is more important than an user making 3 to 4 requests and things like that. I have never seen a security expert recommending to limit the length of the password but I have read many times why you as a developer should never set an artificial limit on the password length.

Christopher
8 years ago
Reply to  Jorge Rivera

I would think it is more so you can allocate dedicated space for a password array of min 8 and no more then 20 char. Regardless of the user ability to remember the password the memory space it would take for users to enter what ever they wanted would be inefficient. This way you can establish a clean uniform array of dedicate value.

Jorge Rivera
8 years ago
Reply to  Christopher

This is only an issue if you are saving the password as plain text since a hash function will always have a fixed length string as a result.

Haider M Rizvi
11 years ago

This post helped me. Thanks.

Lincoln Baxter, III
11 years ago

Hey! Great example – I’d like to suggest a slight adaptation, however. While it is tempting to use a single regular expression for this, I think that there are good reasons to actually split up the regex into multiple checks. Performance is not usually a concern with password checking, so invoking a few more regex calls isn’t really a big deal, like so: http://ocpsoft.org/opensource/guide-to-regular-expressions-in-java-part-1/#comment-4097

chris k
12 years ago

Thanks for this! Saved me a lot of time. Much appreciated Mkyong!

Fernie
10 years ago

Hi All,

What if password should not include easy-to-guess string such as “love”, “happy”, “12345678”, “qwerty”, “asdfgh”, “zxcvb”. How can regular expression validate such strings?

Regards,
Fernie