I currently use this regular expression to check if a string conforms to a few conditions.
The conditions are string must be between 8 and 15 characters long. string must contain at least one number. string must contain at least one uppercase letter. string must contain at least one lowercase letter.
(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,15})$
It works for the most part, but it does not allow special character. Any help modifying this regex to allow special character is much appreciated.
There seems to be a lot of confusion here. The answers I see so far don't correctly enforce the 1+ number/1+ lowercase/1+ uppercase rule, meaning that passwords like abc123, 123XYZ, or AB*&^# would still be accepted. Preventing all-lowercase, all-caps, or all-digits is not enough; you have to enforce the presence of at least one of each.
Try the following:
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,15}$
If you also want to require at least one special character (which is probably a good idea), try this:
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,15}$
The .{8,15}
can be made more restrictive if you wish (for example, you could change it to \S{8,15}
to disallow whitespace), but remember that doing so will reduce the strength of your password scheme.
I've tested this pattern and it works as expected. Tested on ReFiddle here: http://refiddle.com/110
Edit: One small note, the easiest way to do this is with 3 separate regexes and the string's Length
property. It's also easier to read and maintain, so do it that way if you have the option. If this is for validation rules in markup, though, you're probably stuck with a single regex.
Is a regular expression an easier/better way to enforce a simple constraint than the more obvious way?
static bool ValidatePassword( string password )
{
const int MIN_LENGTH = 8 ;
const int MAX_LENGTH = 15 ;
if ( password == null ) throw new ArgumentNullException() ;
bool meetsLengthRequirements = password.Length >= MIN_LENGTH && password.Length <= MAX_LENGTH ;
bool hasUpperCaseLetter = false ;
bool hasLowerCaseLetter = false ;
bool hasDecimalDigit = false ;
if ( meetsLengthRequirements )
{
foreach (char c in password )
{
if ( char.IsUpper(c) ) hasUpperCaseLetter = true ;
else if ( char.IsLower(c) ) hasLowerCaseLetter = true ;
else if ( char.IsDigit(c) ) hasDecimalDigit = true ;
}
}
bool isValid = meetsLengthRequirements
&& hasUpperCaseLetter
&& hasLowerCaseLetter
&& hasDecimalDigit
;
return isValid ;
}
Which do you think that maintenance programmer 3 years from now who needs to modify the constraint will have an easier time understanding?
if (hasUpperCaseLetter && hasLowerCaseLetter && hasDecimalDigit) return true;
inside the foreach
and save a lot of unnecessary iteration.
return false
, because you checked the entire string and didn't find everything you were looking for.
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,15}");
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 lesser than 8 or greater than 15 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 character.";
return false;
}
else
{
return true;
}
}
.{8,15}
will still match a 16 character password
Update to Justin answer above. if you want to use it using Data Annotation in MVC you can do as follow
[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,15}$", ErrorMessage = "Password must be between 6 and 20 characters and contain one uppercase letter, one lowercase letter, one digit and one special character.")]
I would check them one-by-one; i.e. look for a number \d+
, then if that fails you can tell the user they need to add a digit. This avoids returning an "Invalid" error without hinting to the user whats wrong with it.
Try this ( also corrected check for upper case and lower case, it had a bug since you grouped them as [a-zA-Z] it only looks for atleast one lower or upper. So separated them out ):
(?!^[0-9]*$)(?!^[a-z]*$)(?!^[A-Z]*$)^(.{8,15})$
Update: I found that the regex doesn't really work as expected and this is not how it is supposed to be written too!
Try something like this:
(?=^.{8,15}$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?!.*\s).*$
(Between 8 and 15 inclusive, contains atleast one digit, atleast one upper case and atleast one lower case and no whitespace.)
And I think this is easier to understand as well.
Long, and could maybe be shortened. Supports special characters ?"-_
.
\A(?=[-\?\"_a-zA-Z0-9]*?[A-Z])(?=[-\?\"_a-zA-Z0-9]*?[a-z])(?=[-\?\"_a-zA-Z0-9]*?[0-9])[-\?\"_a-zA-Z0-9]{8,15}\z
[\?\"-_a-zA-Z0-9]
will throw an error. You want [-\?\"_a-zA-Z0-9]
.
[-foo]
or [foo-]
(or [^-foo]
or [^foo-]
).
Thanks Nicholas Carey. I was going to use regex first but what you wrote changed my mind. It is so much easier to maintain this way.
//You can set these from your custom service methods
int minLen = 8;
int minDigit 2;
int minSpChar 2;
Boolean ErrorFlag = false;
//Check for password length
if (model.NewPassword.Length < minLen)
{
ErrorFlag = true;
ModelState.AddModelError("NewPassword", "Password must be at least " + minLen + " characters long.");
}
//Check for Digits and Special Characters
int digitCount = 0;
int splCharCount = 0;
foreach (char c in model.NewPassword)
{
if (char.IsDigit(c)) digitCount++;
if (Regex.IsMatch(c.ToString(), @"[!#$%&'()*+,-.:;<=>?@[\\\]{}^_`|~]")) splCharCount++;
}
if (digitCount < minDigit)
{
ErrorFlag = true;
ModelState.AddModelError("NewPassword", "Password must have at least " + minDigit + " digit(s).");
}
if (splCharCount < minSpChar)
{
ErrorFlag = true;
ModelState.AddModelError("NewPassword", "Password must have at least " + minSpChar + " special character(s).");
}
if (ErrorFlag)
return View(model);
Pattern satisfy, these below criteria
Password Length 8 and Maximum 15 character Require Unique Chars Require Digit Require Lower Case Require Upper Case
^(?!.*([A-Za-z0-9]))(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,15}$
(?!.*([A-Za-z0-9])\1{1})
fragment blocks any consecutive repeated character, which isn't mentioned in your criteria and actually reduces the security of the password. You also aren't enforcing the 15-character maximum length. One less important detail: The {1}
is redundant, as are the ?
in all your .*?
quantifiers. .*?
can have a different meaning than .*
, but not in this context.
^^(?=.*[A-Z]{"+minUpperCase+",})(?=.*[a-z]{"+minLowerCase+",})(?=.*[0-9]{"+minNumerics+",})(?=.*[!@#$\-_?.:{]{"+minSpecialChars+",})[a-zA-Z0-9!@#$\-_?.:{]{"+minLength+","+maxLength+"}$
I have modified @Anurag's answer in other question to meet my requirement:
Needed the method to return a list showing where password failed to meet my policy, so first created an Enum with all possible issues:
public enum PasswordPolicyIssue
{
MustHaveNumber,
MustHaveCapitalLetter,
MustHaveSmallLetter,
MustBeAtLeast8Characters,
MustHaveSymbol
}
Then the validation method, that returns bool and has an output List:
public bool MeetsPasswordPolicy(string password, out List<PasswordPolicyIssue> issues)
{
var input = password;
issues = new List<PasswordPolicyIssue>();
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,15}");
var hasMinChars = new Regex(@".{8,}");
var hasLowerChar = new Regex(@"[a-z]+");
var hasSymbols = new Regex(@"[!@#$%^&*()_+=\[{\]};:<>|./?,-]");
if (!hasLowerChar.IsMatch(input))
issues.Add(PasswordPolicyIssue.MustHaveSmallLetter);
if (!hasUpperChar.IsMatch(input))
issues.Add(PasswordPolicyIssue.MustHaveCapitalLetter);
if (!hasMinChars.IsMatch(input))
issues.Add(PasswordPolicyIssue.MustBeAtLeast8Characters);
if (!hasNumber.IsMatch(input))
issues.Add(PasswordPolicyIssue.MustHaveNumber);
if (!hasSymbols.IsMatch(input))
issues.Add(PasswordPolicyIssue.MustHaveSymbol);
return issues.Count() ==0;
}
Success story sharing
/
are just for emphasis that this is regex code. You shouldn't include them if you're using (for example) .NET.