5

Asp.Net MVC password Validation with a Regular Expression

 3 years ago
source link: https://www.aligneddev.net/blog/2018/mvc-password-validation-with-regexp/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Asp.Net MVC Password Validation with a Regular Expression

Originally posted on GeeksWithBlogs.net on May 26th, 2013.

I have requirement (specification) that the password has to be at least 7 characters long and contain a special character (~@#$&*()-_+=) which are all the specials in the number keyboard row. I found that using the RegularExpression DataAnnotations is really slick, but there was a point that caught me for a while.

The problem is that @“.([!@#$&()-+=]+).$” works in the UI, but fails in the unit test. @”[!@#$&()-+=]+” works in the test, but not in the UI (the MVC unobtrusive library wants a full match). When I removed the ‘()’ it works in both. So my solution, after losing some time, is to add the escape before the ‘-’. This works: ^.(?=.[!@#$%^&\(\)_\-+=]).$ (thanks to my co-worker Jason).

Here comes the code:

The Model for the MVC binding. Focus on the RegEx for NewPassword:

public class PasswordResetModel
{
    /// <summary>
    /// Gets or sets the new password.
    /// It must be at least 7 characters and have at least one special character.
    /// </summary>
    /// <value>
    /// The new password.
    /// </value>
    [Required(ErrorMessageResourceType = typeof(AuthenticationModelsResource),
        ErrorMessageResourceName = "NewPasswordRequiredMessage")]
    [StringLength(100, ErrorMessageResourceType = typeof(AuthenticationModelsResource),
        ErrorMessageResourceName = "PasswordTooShortErrorMessage", MinimumLength = 7)]
    [RegularExpression(@"^.*(?=.*[!@#$%^&*\\(\\)_\\-+=\]).*$",
        ErrorMessageResourceType = typeof(AuthenticationModelsResource),
        ErrorMessageResourceName = "PasswordNotStrongEnoughMessage")]
    [DataType(DataType.Password)]
    [Display(ResourceType = typeof(AuthenticationModelsResource), Name = "NewPassword"]
    public string NewPassword { get; set; }

    /// <summary>
    /// Gets or sets the confirm password.
    /// </summary>
    /// <value>
    /// The confirm password.
    /// </value>
    [DataType(DataType.Password)]
    [Display(ResourceType = typeof(AuthenticationModelsResource), Name = "ConfirmNewPassword")]
    [Required(ErrorMessageResourceType = typeof(AuthenticationModelsResource),
       ErrorMessageResourceName = "ConfirmNewPasswordRequiredMessage")]
    [Compare("NewPassword", ErrorMessageResourceType = typeof(AuthenticationModelsResource),
        ErrorMessageResourceName = "PasswordCompareErrorMessage")]
    public string ConfirmPassword { get; set; }
}

The Unit test:

[TestMethod,TestCategory("HomeController")]
public void It_Should_Validate_Password_Doesnt_Have_A_Special_Character()
{
    PasswordResetViewModel vm = new PasswordResetViewModel("match", 10)
                            {
                                PasswordResetModel =
                                {
                                    NewPassword = "test1122",
                                    ConfirmPassword = "test1122"
                                }
                            };
    ((ChangePasswordModel)vm.PasswordResetModel).OldPassword = "test1";
    this.Controller.PasswordReset(vm);

    // assert
    ValidateViewModel(vm.PasswordResetModel, this.Controller);
    Should.BooleanAssertionExtensions.ShouldBeTrue(this.Controller.ModelState.Values.Last()
        .Errors.Any(e => e.ErrorMessage == AuthenticationModelsResource.PasswordNotStrongEnoughMessage));
}

The ValidateViewModel method:

protected static void ValidateViewModel<TVm, TC>(TVm viewModelToValidate, TC controller) where TC : Controller
{
    var modelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => viewModelToValidate, viewModelToValidate.GetType());
    var validator = ModelValidator.GetModelValidator(modelMetadata, controller.ControllerContext);
    var result = validator.Validate(viewModelToValidate);
    foreach (var validationResult in result)
    {
        if (!string.IsNullOrWhiteSpace(validationResult.MemberName))
        {
            controller.ModelState.AddModelError(validationResult.MemberName, validationResult.Message);
        }
        else
        {
            controller.ModelState.AddModelError(string.Empty, validationResult.Message);
        }
    }
}

The MVC Unobtrusive Validation library wants a complete match (from the source code):

$jQval.addMethod("regex", function (value, element, params) {
    var match;
    if (this.optional(element)) {
        return true;
    }

    match = new RegExp(params).exec(value);
    return (match && (match.index === 0) && (match\[0\].length === value.length));
});


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK