I've got this Regex as a data annotation on a password field in a C# .NET MVC project.
[RegularExpression("(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[*+\\/|!\"£$%^&*()#[\\]#~'?><,.=-_]).{6,}", ErrorMessage = "Password must be between 6 and 20 characters and contain one uppercase letter, one lowercase letter, one digit and one special character.")]
I want to make the following passwords invalid:-
Testing
Testing1
TesTinG123
The following would be valid:-
Testing1*
T&sting123*
%F&y5HD$S
I would like a minimum of 6 characters, with at least one uppercase, one lower case, one digit and one special character. I hope the above regex would do it, but it lets Testing12 and Tester12 through as valid passwords.
What can I change in the above to get what I am expecting? I assumed the above requires one uppercase, one lowercase, one numeric and one special character but obviously I am wrong?
Thanks in advance!
You forgot to escape ] properly (it is advised to even put it at the start of the character class so that in .NET it could be parsed as a literal ] - for the client side validation, it needs to be escaped even there) and remember that a hyphen inside a character class creates a range (e.g. [=-_]), so it must be put at the end/start of the character class or at the end to denote a literal -).
Use
"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\]*+\\/|!\"£$%^&*()#[#~'?><,.=_-]).{6,}$"
^^ ^
Or, if you just want to require at least 1 char that is not alphanumeric, use
"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_]).{6,}$"
where [\W_] matches any char but a word char (i.e. [^\p{L}\p{N}_] or - on client side - [^a-zA-Z0-9_]) + _.
The ^ and $ anchors are redundant in the RegularExpressionAttribute pattern, but they won't do any harm.
See the regex demo.
Related
How do I add underscore as a part of my regex string.
Here is my string that checks for uppercase, lowercase, numbers and special characters. The rest of the special characters work. Validation isn't working for underscores.
#"^[^\s](?=(.*[A-Za-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W]){1,})(?=(.*[!##$%^&*()-+=\[{\]};:<>|_.\\/?,\-`'""~]{1,})).*[^\s]$"
Any ideas?
Thanks
This is the regex that AWS Cogito uses, it should apply to your situation:
#"^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[\^$*.\[\]{}\(\)?\-“!##%&\/,><’:;|_~`])\S{8,99}$"
You can check regexes at http://regexstorm.net, it's faster than building your application everytime.
I've approached it like this: I took your requirements and made them into separate positive lookaheads:
Check for:
uppercase (?=.*[A-Z])
lowercase (?=.*[a-z]) (note that I broke A-Z and a-z up into separate groups)
numbers (?=.*\d)
special characters (?=.*[!##$%^&*()-+=\[{\]};:<>|_.\\/?,\-`'""~])
You can then combine them in any order and I've combined them in the same order as I listed them above and anchored it with the beginning of the line using ^. Don't add any extra matches before, in-between or after the groups in your requirement that could cause the regex to enforce a certain ordering of the groups:
The lookahead for any non-word character \W makes it impossible to match Underscore1_ since it will only match on "anything other than a letter, digit or underscore" - which is all Underscore1_ contains.
The starting [^\s] (and ending [^\s]) that consumes one character is likely destroying a lot of good matches. Underscore1_ or _1scoreUnder shouldn't matter, but if you start with _ and consume it with [^\s] like you do, the later lookahead for a special character will fail (unless you have a second special character in the password).
#"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!##$%^&*()-+=\[{\]};:<>|_.\\/?,\-`'""~])"
If you have a minimum length requirement of, say, 7 characters, you just have to add .{7,}$ to the end of the regex, making it:
#"^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[!##$%^&*()-+=\[{\]};:<>|_.\\/?,\-`'""~]).{7,}$"
Without a minimum length, a password of one character from each group will be enough, and since there are 4 groups, a password with only 4 characters will pass the filter.
I see no point in putting an upper length limit into the regex. If the user interface has accepted a string that is thousands of characters long, then why reject it for being too long later? The length of what you store is probably going to be much smaller anyway since you'll be storing the bcrypt/scrypt/argon2/... encoded password.
Suggestion: Also add space (or even whitespaces) to the list of special characters.
In you regexp add underscore in 3rd Capturing Group regex101
#"^[^\s](?=(.*[A-Za-z]){1,})(?=(.*[\d]){1,})(?=(.*[\W_]){1,})(?=(.*[!##$%^&*()-+=\[{\]};:<>|_.\\/?,\-`'""~]{1,})).*[^\s]$"
I already have an email address regular expression FROM RFC 2822 FORMAT
[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*#(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?
but want to modify it to include the following some new conditions:
at least one full stop
at least one # character
no consecutive full stops
must not start/end with special characters i.e. should only start/end with [0-9a-zA-Z]
should still follow RFC specification for regular expression rules.
Currently the above one allows the email to start with special characters. Also it is allowing two consecutive full stops (except for domain name which is fine, so test#test..com fails and its correct).
Thanks.
^[a-zA-Z0-9]+(?:\.?[\w!#$%&'*+/=?^`{|}~\-]+)*#[a-zA-Z0-9](?:\.?[\w\-]+)+\.[A-Za-z0-9]+$
No .. and at least 1 . and 1 #.
Also starts/ends with letters/numbers.
The ^ (start) and $ (end) were just added to match a whole string, not just a substring. But you could replace those by a word boundary \b.
An alternative where the special characters aren't hardcoded:
^(?!.*[.]{2})[a-zA-Z0-9][^#\s]*?#[a-zA-Z0-9][^#\s]*?\.[A-Za-z0-9]+$
In my demo MVC Application I have the following validation rules for validating my domain model classes.
RuleFor(m => m.Password)
.Matches(#"^(?=(\d){2,})(?=([a-z])+)(?=(\.\$\~\&)*)").WithMessage("Password should contain at least 2 digits");
But the password validation fails .
Basically I want to validate that a password input value should at least contain 2 digits, at least either one of the special characters (.$~&) and at least one alphabet in any order.
They can appear in any order.
Basically I should match the strings like
'a2ss1~A33',
'678.&aA88'
but not
'aaa2sfhdjkf^',
'aass'.
Also I just came across lookahead s in regex.
I still have a doubt why cant just we have the rule for validating the password field ?
.Matches(#"^((\d){2,})(.*[a-zA-Z])([\.\$\~\&]*)").WithMessage("Password should contain at least 2 digits");
When to use lookaheads in regex and when not to ?
You can use
^(?=(\D*\d){2})(?=[^A-Za-z]*[A-Za-z])(?=[^.$~&]*[.$~&]).*
See the regex demo.
The regex matches:
^ - start of string
(?=(\D*\d){2}) - 2 digits anywhere in the string are required
(?=[^A-Za-z]*[A-Za-z]) - an ASCII letter is required somewhere in a string
(?=[^.$~&]*[.$~&]) - the symbol from the [.$~&] set is required
.* - (optional, remove if full string match is not required) matches all characters other than a newline up to the end of the line
Lookaheads enable several checks from the same position in string (here, at the very beginning as they are all placed right after ^). The regex ^((\d){2,})(.*[a-zA-Z])([\.\$\~\&]*) requires 2 or more digits at the beginning, followed with any 0+ characters other than a newline followed with 1 letter followed with 0+ some special symbols. There can be anything else after that, since you are not checking the end of the string.
Brand new to using Regular Expressions. I have one that currently accepts alphanumeric characters only. I need to add the following special characters to the regex:
# #$%*():;"',/? !+=-_
Here is the regular expression:
RegularExpression(#"^[a-zA-Z\s.,0-9-]{1,30}$",
When I try to add the special characters, I alter the Regex like so:
RegularExpression(#"^[a-zA-Z\s.,0-9-# #$%*():;"',/? !+=-_]{1,30}$"
However this throws an error starting with the ' character that says Newline in constant.
I've tied to escape both the " and the ' characters, however without any luck.
the problem comes from the double quote that need to be escaped (""), not from the single quote.
#"^[a-zA-Z\s.,0-9##$%*():;""'/?!+=_-]{1,30}$"
note that the - must be at the last (or first) position in a character class, since it has a special meaning (define ranges)
These regexs' are equivalent to yours.
Both use tilde ~ as the delimeter.
Both use double quotes on the regex strings.
Note that in order for the the dash - in class to be interpreted literally and not as a range operator, it must exist somewhere disambiguous, or be escaped.
A good place to put it is between valid ranges (or at the beginning or end of a class).
For example [a-z-0-9] is a good place.
Edit - '-' Literal may have to be escaped or beginning/end of class. (This case was for Perl/PCRE engines)
This one ^[a-z-A-Z0-9_\s.,##$%*():;"',/?!+=]{1,30}$ is your regex without duplicate chars.
To make it more readable noting that the word class is contained, it can be reduced to
^[\w-\s.,##$%*():;"',/?!+=]{1,30}$
Edit - Php test cases removed.
NET. I have created a regex validator to check for special characters means I donot want any special characters in username. The following is the code
Regex objAlphaPattern = new Regex(#"[a-zA-Z0-9_#.-]");
bool sts = objAlphaPattern.IsMatch(username);
If I provide username as $%^&asghf then the validator gives as invalid data format which is the result I want but If I provide a data s23_#.-^&()%^$# then my validator should block the data but my validator allows the data which is wrong
So how to not allow any special characters except a-z A-A 0-9 _ # .-
Thanks
Sunil Kumar Sahoo
There's a few things wrong with your expression. First you don't have the start string character ^ and end string character $ at the beginning and end of your expression meaning that it only has to find a match somewhere within your string.
Second, you're only looking for one character currently. To force a match of all the characters you'll need to use * Here's what it should be:
Regex objAlphaPattern = new Regex(#"^[a-zA-Z0-9_#.-]*$");
bool sts = objAlphaPattern.IsMatch(username);
Your pattern checks only if the given string contains any "non-special" character; it does not exclude the unwanted characters. You want to change two things; make it check that the whole string contains only allowed characters, and also make it check for more than one character:
^[a-zA-Z0-9_#.-]+$
Added ^ before the pattern to make it start matching at the beginning of the string. Also added +$ after, + to ensure that there is at least one character in the string, and $ to make sure that the string is matched to the end.
Change your regex to ^[a-zA-Z0-9_#.-]+$. Here ^ denotes the beginning of a string, $ is the end of the string.