Please tell me what's the point of the [DataType (DataType.Password)] annotation? For example, if I use the @ Html.Password helper view or simply write textbox new {@type = "password"} to the helper, then when I enter this field, the characters will be displayed as an asterisk for password security. But I tried in the model to put an annotation with a password type on the property. Nothing like that happens. So what is this annotation for?
2 answers
DataAnnotations used to validate the model's fields, that is, if it is Password , then you can specify through the annotation, suppose that the password must begin with a capital letter, the minimum / maximum number of characters in the password, you can specify that the password should be special. characters and so on.
Example:
[Required] [StringLength(18, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] [RegularExpression(@"((?=.*[az]+)(?=.*[AZ]+)(?=.*[0-9]+)(?=.*[!@#$%^&*()_+=\[{\]};:<>|./?,-]))")] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } Data Annotation to validate confirm password
When using the ASP.NET Identity authentication and authorization system, we can encounter the following problem: when entering a password, the built-in validation logic is triggered, and we cannot change this logic using the standard validation attribute mechanism. But what if we need to set a different minimum password length, etc. And despite the fact that the built-in validation logic is hidden from our eyes, we can override it. For the validation mechanism, the UserManager class PasswordValidator property is responsible. It stores a validation object that we can change.
If we go to the IdentityConfig.cs file in the App_Start folder, then in the definition of the ApplicationUserManager class we can see the use of the password validator:
var manager = new ApplicationUserManager (new UserStore<ApplicationUser> (context.Get<ApplicationDbContext>())); //.......................... manager.PasswordValidator = new PasswordValidator { RequiredLength = 6, RequireNonLetterOrDigit = true, RequireDigit = true, RequireLowercase = true, RequireUppercase = true, }; To determine password validation, the built-in class PasswordValidator is used here, which has the following properties:
RequiredLength: minimum password length;RequireNonLetterOrDigit: if true, then the password will have to have at least one character that is not alphanumeric;RequireDigit: if true, then the password will need to have at least one digit;RequireLowercase: if true, then the password will need to have at least one lowercase character;RequireUppercase: if true, then the password will need to have at least one uppercase character.
For most cases, this functionality is enough, we can set the minimum password length, input alphanumeric, or non-alphanumeric characters. However, if we need more complex validation logic, we will have to define our own validator class.
The validator object represents the IIdentityValidator interface IIdentityValidator . In this case, an instance of the PasswordValidator class is used as such an object, which sets the minimum password length and a number of other rules. However, we can do nothing more with this validator. Therefore, to create more sophisticated validation logic, we need to create a separate class.
So, create the following class:
public class CustomPasswordValidator : IIdentityValidator<String> { public Int32 MinRequiredLength { get; private set; } // минимальная длина public CustomPasswordValidator(Int32 MinRequiredLength) => this.MinRequiredLength = MinRequiredLength; public Task<IdentityResult> ValidateAsync(String item) { var hasLowerChar = new Regex(@"[az]+"); var hasUpperChar = new Regex(@"[AZ]+"); var hasMiniMaxChars = new Regex($@".{MinRequiredLength, 15}"); var hasNumber = new Regex(@"[0-9]+"); var hasSymbols = new Regex(@"[!@#$%^&*()_+=\[{\]};:<>|./?,-]"); if (String.IsNullOrWhiteSpace(item)) throw new Exception("Пароль не должен быть пустым"); if (!Regex.IsMatch(item, hasLowerChar.ToString())) { return Task.FromResult( IdentityResult.Failed("Пароль должен содержать хотя бы одну строчную букву")); } else if (!Regex.IsMatch(item, hasUpperChar.ToString())) { return Task.FromResult( IdentityResult.Failed("Пароль должен содержать хотя бы одну заглавную букву")); } else if (!Regex.IsMatch(item, hasMiniMaxChars.ToString())) { return Task.FromResult( IdentityResult.Failed($"Пароль должен быть не менее {MinRequiredLength} символов")); } else if (!Regex.IsMatch(item, hasNumber.ToString())) { return Task.FromResult( IdentityResult.Failed("Пароль должен содержать хотя бы одно числовое значение")); } else if (!Regex.IsMatch(item, hasSymbols.ToString())) { return Task.FromResult( IdentityResult.Failed("Пароль должен содержать хотя бы один специальный символ")); } return Task.FromResult(IdentityResult.Success); } } The validator class implements the IIdentityValidator interface, which has one method ValidateAsync. This method accepts a string parameter, to the place of which then the string of the validated password will be transferred to the program. He can do the following checks:
- Password check for void;
- Check for the content of lowercase letters;
- Check for the content of capital letters;
- Check for min./max. Characters;
- Check for the content of numbers;
- Check for the content of specials. characters.
And then also in the definition of the ApplicationUserManager class we can use it:
var manager = new ApplicationUserManager (new UserStore<ApplicationUser> (context.Get<ApplicationDbContext>())); //.............................. manager.PasswordValidator = new CustomPasswordValidator(5); - Yaroslav, well, and what prevents me from doing all the necessary validations for me, the same is valid for required and range without specifying that this field is a password? I can do it, too. - Andrei
- Yaroslav, you gave the wrong answer, it turns out you can do what I want and gave the correct answer in another topic. I will issue as an answer. - Andrei
- @ Andrei, I can do it too, and I didn’t say that you can’t do it! - Yaroslav
- @Andrey, you asked about DataAnnotations, I answered, but you can interpret it as you like. I wrote the example of
Passwordfor what it is needed, well, you have the right to do it for a friend. - Yaroslav - Yaroslav, I agree, I did not quite correctly formulated the question, you basically answered the wording that I put. And what specifically interested me, I gave my answer. Your, too, accept. - Andrei
In order for the field to be annotated with [DataType (DataType.Password)] as a password and when entering a value in this field, they are marked with asterisks, as it should be in passwords, use the EditorForper helper more detailed answer in the topic at: https: // stackoverflow. com / questions / 6044922 / model-does-not-apply-datatype-password