3

I have to provide a data annotation regex for a password that's specified as:

min 8 chars
min 1 upper
min 1 lower
min 1 numeric
min 1 special char which can ONLY be one of the following:$|~=[]'_-+@. (and the password can contain no other special chars besides these)

It's the exclusion of special characters which is giving me the headache.

I've come up with this but it just does not work:

"^.*(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[\d])**(?(?!.*[^$|~=[\]'_\-+@.])|([^\W\w])).*$**

It resolves everything I enter as invalid.

Whereas this (for the special chars) on its own does work:

"(?(?!.*[^$|~=[\]'_\-+@.])|([^\W\w])).*$"

and I know the first part works, so what am I missing to make them work together?

Alternatively, is there a much simpler way of achieving this?

(.NET environment)

nhahtdh
  • 55,989
  • 15
  • 126
  • 162
user2300874
  • 33
  • 1
  • 4

1 Answers1

3

If you really want to do that in one regex pattern:

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[$|~=[\]'_+@.-])[a-zA-Z0-9$|~=[\]'_+@.-]{8,}$

That should do the trick. We require, the lower case, upper case letter, digit and symbol with lookaheads. Note that in the character class, you need to move - to the end or escape it. Otherwise it creates a character range you don't want. Then we use normal matching to ensure that there are only the allowed characters, and at least 8 of them.

However, it's usually a much better approach to do multiple tests. Run these patterns individually:

[a-z]                     // does the input contain a lower case letter?
[A-Z]                     // does the input contain an upper case letter?
\d                        // does the input contain a digit?
[$|~=[\]'_+@.-]           // does the input contain one of the required symbols?
[^a-zA-Z0-9$|~=[\]'_+@.-] // are there invalid characters?

where the first 4 should return true and the last one should return false. In addition you can check input.Length >= 8. This makes for much more readable code and will allow you to issue an appropriate error message about which condition is not fulfilled.

In fact, since the last pattern ensures that there are only the desired characters, we can simplify the "there has to be one symbol condition" to [^a-zA-Z0-9] (in both approaches). But I'm not sure whether that makes things more or less readable.

Martin Ender
  • 43,427
  • 11
  • 90
  • 130
  • I knew there had to be a simpler way. You're a life saver! Many Thanks! – user2300874 Apr 20 '13 at 00:15
  • @user2300874 you're welcome. please consider accepting the answer, by clicking the check mark next to it. that will show future visitors that (and how) your problem has been solved and will give me some credit (and a little to you as well). See [this section of the FAQ](http://stackoverflow.com/faq#howtoask) for more information on accepting answers. – Martin Ender Apr 20 '13 at 00:18