3

This is the fluent validation for the password in my C# application so far

RuleFor(request => request.Password)
    .NotEmpty()
    .MinimumLength(8)
    .Matches("[A-Z]+").WithMessage("'{PropertyName}' must contain one or more capital letters.")
    .Matches("[a-z]+").WithMessage("'{PropertyName}' must contain one or more lowercase letters.")
    .Matches(@"(\d)+").WithMessage("'{PropertyName}' must contain one or more digits.")
    .Matches(@"[""!@$%^&*(){}:;<>,.?/+\-_=|'[\]~\\]").WithMessage("'{ PropertyName}' must contain one or more special characters.")
    .Matches("(?!.*[£# “”])").WithMessage("'{PropertyName}' must not contain the following characters £ # “” or spaces.")
    .Must(pass => !blacklistedWords.Any(word => pass.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0))
        .WithMessage("'{PropertyName}' contains a word that is not allowed.");

The following part currently doesn't work

.Matches("(?!.*[£# “”])").WithMessage("'{PropertyName}' must not contain the following characters £ # “” or spaces.")

For example when the password is 'Hello12!#' no validation errors are returned. £ # “” and spaces should not be allowed in a password and if any of these are present the validation should fail with the ''{PropertyName}' must not contain the following characters £ # “” or spaces.' error message.

How to amend this to make it work as it should?

imsan
  • 359
  • 4
  • 17
  • 1
    Why restrict passwords in that way? – Enigmativity Oct 05 '20 at 09:23
  • This part `(?!.*[£# “”])` means that the listed characters should not be present, but `\W` does match all those characters – The fourth bird Oct 05 '20 at 09:25
  • 1
    Tried `.Matches(@"[""!@$%^&*(){}:;<>,.?/+\-_=|'[\]~\\]")` yet? – Wiktor Stribiżew Oct 05 '20 at 09:50
  • @WiktorStribiżew yes that part works thanks, updated the question as it wasn't very clear what I was asking, the part that doesn't currently work is the not allowing spaces and the £ # and “” characters. If any of these are in the password it should return the validation error but it doesn't. Any ideas on this please? – imsan Oct 05 '20 at 10:35
  • Tried `.Matches("^[^£# “”]*$")`? – Wiktor Stribiżew Oct 05 '20 at 10:37
  • @WiktorStribiżew that appears to work! Can you explain what it means? I'm confused as the previous lines return the error if the password **doesn't** contain a lowercase letter/upper case letter/digit/symbol. What in the line that you suggested makes it return the error when the password **does** contain one of the specified characters? – imsan Oct 05 '20 at 11:40

1 Answers1

5

You can use

RuleFor(request => request.Password)
    .NotEmpty()
    .MinimumLength(8)
    .Matches("[A-Z]").WithMessage("'{PropertyName}' must contain one or more capital letters.")
    .Matches("[a-z]").WithMessage("'{PropertyName}' must contain one or more lowercase letters.")
    .Matches(@"\d").WithMessage("'{PropertyName}' must contain one or more digits.")
    .Matches(@"[][""!@$%^&*(){}:;<>,.?/+_=|'~\\-]").WithMessage("'{ PropertyName}' must contain one or more special characters.")
    .Matches("^[^£# “”]*$").WithMessage("'{PropertyName}' must not contain the following characters £ # “” or spaces.")
    .Must(pass => !blacklistedWords.Any(word => pass.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0))
        .WithMessage("'{PropertyName}' contains a word that is not allowed.");

Note:

  • .Matches(@"[][""!@$%^&*(){}:;<>,.?/+_=|'~\\-]") - this matches an ASCII punctuation anywhere inside a string, and if not, the error pops up with the corresponding message
  • .Matches("^[^£# “”]*$") - this matches the whole string each char of which cannot be £, #, space, or . If any char is equal to at least one of these chars, the error message pops up.

Regarding [][""!@$%^&*(){}:;<>,.?/+_=|'~\\-], the ] is the first char in the character class and does not have to be escape. The - is placed at the end of the character class and does not have to be escaped either.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563