2

I looked around on stackoverflow, etc, but haven't found a good answer for this..Does regex support writing a rule like this? If so is there any regex experts our there who can help me write this, I am a big newb to regex and in a time crunch...

I know I can do this with a manual function in c# using c# char, number methods, but I would like to use regex if I can for this..

Requirement :

  • At least 8 characters long
    • 2 letters
    • 2 digits
    • 1 Upper case
    • 1 Lower case
    • 1 Symbol
6
  • 7
    If these are the actual rules you're going to use, I hate you. :) Commented Jun 5, 2013 at 16:40
  • I didn't make up these rules :) Commented Jun 5, 2013 at 16:40
  • 1
    Exactly 8 chars or at least 8 chars? Commented Jun 5, 2013 at 16:41
  • 3
    @MikeChristensen Don't forget a hieroglyph. Commented Jun 5, 2013 at 16:42
  • 1
    Regex would be way too much complex. Commented Jun 5, 2013 at 16:46

4 Answers 4

21

You can use this regex

^(?=(.*\d){2})(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z\d]).{8,}$
    ---------  --------------------- --------------- -----
        |               |                    |          |->match 8 or more characters
        |               |                    |->match further only if theres anything except letter or digit
        |               |->match further only if there is an upper-lower case letter
        |
        |->match further only if there are two digits anywhere

Demo

Sign up to request clarification or add additional context in comments.

16 Comments

@Anirudh - Ah after the edit, it works now.. I wouldn't use it but +1 for hacking that together.
+1, Never know there is such thing as (?= in regular expression. Great work.
I will test this a while and mark this as answer if it passed my validation tests. Thanks.
@kyleb - One drawback with this is you can't tell the user why their password is invalid, you can only tell them it isn't.
That is true I can't tell them what is wrong, but that is not a requirement right now. If it does become one I will revert to using C# instead.
|
17

You are much better off writing a simple validation routine for a password that has all of these checks.

A regular expression doesn't seem as the best (or most extensible) solution for this particular problem.

if(password.Length < 8)
  return false;

var letters = 0;
var digits = 0;
var uppers = 0;
var lowers = 0;
var symbols = 0;
foreach(var ch in password)
{
   if (char.IsLetter(ch)) letters++;
   if (char.IsDigit(ch)) digits++;
   ....
} 

if(letters < 2) return false;
...

4 Comments

While a regex would work, this is significantly more maintainable solution.
I am leaning towards this but I want to see if anyone can create a regular expression like this first..
+1, nice, conceivable and more maintainable, as to be compared to long-long regular expressions.
@kyleb, I am attempting too, but from what I have picture, it is way too long.
5

I recommend going the way Oded's answer did, but I think LINQ is a more readable and explicit validation mechanism in this case.

string p = "psW%Rd32";
return p.Length >= 8 &&
    p.Count(c => char.IsDigit(c)) >= 2 &&
    p.Count(c => char.IsUpper(c)) >= 1 &&
    p.Count(c => char.IsLower(c)) >= 1) ...

6 Comments

Though I like it, you are iterating multiple times over the string (once per Count).
return p.Length == 8 is wrong. you must have AT LEAST 8 characters
+1 - Though it would require many iterations through the string, it's easy to read and well organized.
I knew you'd pick on performance. :) I assumed this is for realtime validation of a textbox, not iterating over thousands of passwords after the fact. In this case we're iterating realistically no more than 1-2 dozen characters, any performance benefits will not be felt on any CPU from the last 15 years.
@Damith Depends what the OP wants to enforce, it's just an example.
|
3

You may try this method.

 private bool ValidatePassword(string password, out string ErrorMessage)
{
    var input = password;
    ErrorMessage = string.Empty;

    if (string.IsNullOrWhiteSpace(input))
    {
        throw new Exception("Password should not be empty");
    }

    var hasNumber = new Regex(@"[0-9]+");
    var hasUpperChar = new Regex(@"[A-Z]+");
    var hasMiniMaxChars = new Regex(@".{8,8}");
    var hasLowerChar = new Regex(@"[a-z]+");
    var hasSymbols = new Regex(@"[!@#$%^&*()_+=\[{\]};:<>|./?,-]");

    if (!hasLowerChar.IsMatch(input))
    {
        ErrorMessage = "Password should contain At least one lower case letter";
        return false;
    }
    else if (!hasUpperChar.IsMatch(input))
    {
        ErrorMessage = "Password should contain At least one upper case letter";
        return false;
    }
    else if (!hasMiniMaxChars.IsMatch(input))
    {
        ErrorMessage = "Password should not be less than or greater than 8 characters";
        return false;
    }
    else if (!hasNumber.IsMatch(input))
    {
        ErrorMessage = "Password should contain At least one numeric value";
        return false;
    }

    else if (!hasSymbols.IsMatch(input))
    {
        ErrorMessage = "Password should contain At least one special case characters";
        return false;
    }
    else
    {
        return true;
    }
}

1 Comment

-1 : this fails Accessibility Standards - all error messages should be returned in a single response. This method could cause multiple attempts of the same input with differing error responses. It should be refactored to test all rules and return a collection of errors

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.