Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core 7
Кроме проверки пароля в ASP.NET Core Identity также валидируется и пользователь. В частности, если мы введем при регистрации некорректные данные для поля Email, то получим ошибки валидации пользователя:
В данном случае ошибка говорит о том, что email некорректен и должен содержать только алфавитно-цифровые символы.
За валидацию пользователя по умолчанию отвечает класс UserOptions, который определяет следующие свойства:
AllowedUserNameCharacters
: если равно true, то юзернейм должен содержать только алфавитно-цифровые символы
RequireUniqueEmail
: если равно true, то email пользователя должен быть уникальным
Для применения этих свойств изменим установку контекста данных в методе ConfigureServices()
в классе Startup:
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<User, IdentityRole>(opts => { opts.User.RequireUniqueEmail = true; // уникальный email opts.User.AllowedUserNameCharacters = ".@abcdefghijklmnopqrstuvwxyz"; // допустимые символы }) .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddControllersWithViews(); }
Свойство opts.User
как раз и представляет класс UserOptions
.
Этот способ работает, но все же он имеет недостатки:
Несмотря на то, что разрешены только алфавитные символы, в сообщении все равно говорится, что email должен содержать алфавитные или цифровые символы. И во-вторых, сообщения отображаются на английском языке. И в этом случае мы можем полностью переопределить логику валидации, создав свой класс валидатора.
Класс валидатора должен реализовать интерфейс IUserValidator<T>
:
public interface IUserValidator<TUser> where TUser : class { Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user); }
Метод ValidateAsync()
вызывается при валидации адреса электронной почты. В качестве параметров в метод передаются объект UserManager и
валидируемый пользователь.
Теперь создадим класс-валидатор CustomUserValidator:
using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; namespace CustomIdentityApp.Models { public class CustomUserValidator : IUserValidator<User> { public Task<IdentityResult> ValidateAsync(UserManager<User> manager, User user) { List<IdentityError> errors = new List<IdentityError>(); if (user.Email.ToLower().EndsWith("@spam.com")) { errors.Add(new IdentityError { Description = "Данный домен находится в спам-базе. Выберите другой почтовый сервис" }); } if (user.UserName.Contains("admin")) { errors.Add(new IdentityError { Description = "Ник пользователя не должен содержать слово 'admin'" }); } return Task.FromResult(errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray())); } } }
Здесь проверяются пара условий: наличие слова "admin" и домен электронного адреса. В зависимости от результатов проверки добавляются соответствующие ошибки в
коллекцию errors. И если ошибок не будет найдено, что значит валидация прошла успешно, и возвращается значение IdentityResult.Success
.
Теперь применим наш валидатор. Для этого добавим установку валидатора в метод ConfigureServices()
класса Startup:
public void ConfigureServices(IServiceCollection services) { services.AddTransient<IUserValidator<User>, CustomUserValidator>(); services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<User, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>(); services.AddControllersWithViews(); }
И в этом случае, если мы введем некорректные значения, то увидим сообщения из нашего валидатора:
Также для создания валидатора мы можем унаследовать свой класс от класса UserValidator
:
public class CustomUserValidator : UserValidator<User> { public override Task<IdentityResult> ValidateAsync(UserManager<User> manager, User user) { List<IdentityError> errors = new List<IdentityError>(); if (user.Email.ToLower().EndsWith("@spam.com")) { errors.Add(new IdentityError { Description = "Данный домен находится в спам-базе. Выберите другой почтовый сервис" }); } if (user.UserName.Contains("admin")) { errors.Add(new IdentityError { Description = "Ник пользователя не должен содержать слово 'admin'" }); } return Task.FromResult(errors.Count == 0 ? IdentityResult.Success : IdentityResult.Failed(errors.ToArray())); } }
Этот класс также реализует интерфейс IUserValidator, поэтому для его переопределения мы можем изменить метод ValidateAsync()
. Результат будет тем же, что и в предыдущем случае.