Ismael Alsabea
Ismael Alsabea

Reputation: 41

Password Validation with Regex Java

I am trying to figure out a regex to match a password that contains

  1. one upper case letter.
  2. one number
  3. one special character.
  4. and at least 4 characters of length

the regex that I wrote is

^((?=.*[0-9])(?=.*[A-Z])(?=.*[^A-Za-z0-9])){4,}

however it is not working, and I couldn't figure out why.

So please can someone tell me why this code is not working, where did I mess up, and how to correct this code.

Upvotes: 1

Views: 139

Answers (2)

Jan
Jan

Reputation: 43199

You could come up with sth. like:

^(?=.*[A-Z])(?=.*\d)(?=.*[!"§$%&/()=?`]).{4,}$

In multiline mode, see a demo on regex101.com.
This approach specifies the special characters directly (which could be extended, obviously).
From the following list only the bold ones would satisfy these criteria:

  • test
  • Test123!
  • StrongPassword34?
  • weakone
  • Tabaluga"12???

You can still enhance this expression by being more specific and requiring contrary pairs. Just to remind you, the dot-star (.*) brings you down the line and then backtracks eventually. This will almost always require more steps than to directly look for contrary pairs.
Consider the following expression:

^                    # bind the expression to the beginning of the string
(?=[^A-Z\n\r]*[A-Z]) # look ahead for sth. that is not A-Z, or newline and require one of A-Z
(?=[^\d\n\r]*\d)     # same construct for digits
(?=\w*[^\w\n\r])     # same construct for special chars (\w = _A-Za-z0-9)
.{4,}
$

You'll see a significant reduction in steps as the regex engine does not have to backtrack everytime.

Upvotes: 0

Pshemo
Pshemo

Reputation: 124285

Your regex can be rewritten as

^(
  (?=.*[0-9])
  (?=.*[A-Z])
  (?=.*[^A-Za-z0-9])
 ){4,}

As you see {4,} applies to group which doesn't let you match any character since look-around is zero-width, which effectively means "4 or more of nothing".

You need to add . before {4,} to let your regex handle "and at least 4 characters of length" point (rest is handled by look-around).
You can remove that capturing group since you don't really need it.

So try with something like

^(?=.*[0-9])(?=.*[A-Z])(?=.*[^A-Za-z0-9]).{4,}

Upvotes: 1

Related Questions