深入理解Aspnet Core之Identity(5)

主题

本篇我将会介绍验证用户的机制当账户被创建的时候,同样 这个过程主要有IUserValidator这个接口来实现的,和密码验证一样Identity同样也内置已经实现好的账户验证。账户验证的比较简单,我会先介绍内置的IUserValidator的使用,然后会简单介绍一些源代码,最后会演示怎实现一个自定义的IUserValidator。


使用内置的IUserValidator来定义用户户名的规则

用户名验证规则是在Startup类 里面进行配置的,通过用IdentityOptions.User进行配置,IdentityOptions.User是UserOptions类的实例。UserOptions属性的列表如下:

  • AllowedUserNameCharacters :类型string 代表用户创建用户名可以使用的字符,默认为:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+
  • RequireUniqueEmail :类型 bool,true 代表创建账户使用的email必须是没有被用过的。

现在Startup类中的ConfigureServices方法配置用户名验证规则,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public void ConfigureServices(IServiceCollection services)
{
//注入自定义密码验证类
services.AddTransient<IPasswordValidator<AppUser>,
CustomPasswordValidator>();

services.AddDbContext<AppIdentityDbContext>(options =>
options.UseSqlServer(
Configuration["Data:AppStoreIdentity:ConnectionString"]));
//配置
services.AddIdentity<AppUser, IdentityRole>(opts => {
//配置用户名验证规则
opts.User.RequireUniqueEmail = true;
opts.User.AllowedUserNameCharacters = "testabc";
//配置密码强度
opts.Password.RequiredLength = 6;
opts.Password.RequireNonAlphanumeric = false;
opts.Password.RequireLowercase = false;
opts.Password.RequireUppercase = false;
opts.Password.RequireDigit = false;
}).AddEntityFrameworkStores<AppIdentityDbContext>()
.AddDefaultTokenProviders();
services.AddMvc();
}

  • 当用户创建账户时候要求email必须是未使用过的,用户名仅包含 testabc 这里面的字符。
    我们启动网站,创建一个账户,看一下配置是否生效,结果如下图:
    avatar

自定义用户验证

  • 虽然内置的用户验证可以满足很多场景,但是假如我们要求创建的拥护都要包含test@163.com这个后缀时,我们就需要自定义一个用户验证类了。

    IUserValidator接口的源代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // Copyright (c) .NET Foundation. All rights reserved.
    // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

    using System.Threading;
    using System.Threading.Tasks;

    namespace Microsoft.AspNetCore.Identity
    {
    /// <summary>
    /// Provides an abstraction for user validation.
    /// </summary>
    /// <typeparam name="TUser">The type encapsulating a user.</typeparam>
    public interface IUserValidator<TUser> where TUser : class
    {
    /// <summary>
    /// Validates the specified <paramref name="user"/> as an asynchronous operation.
    /// </summary>
    /// <param name="manager">The <see cref="UserManager{TUser}"/> that can be used to retrieve user properties.</param>
    /// <param name="user">The user to validate.</param>
    /// <returns>The <see cref="Task"/> that represents the asynchronous operation, containing the <see cref="IdentityResult"/> of the validation operation.</returns>
    Task<IdentityResult> ValidateAsync(UserManager<TUser> manager, TUser user);
    }
    }
  • 该接口很简单就包含了 ValidateAsync方法,用于验证用户名,

    实现IUserValidator 接口

    在Infrastructure文件夹中创建一个CustomUserValidator C#文件,代码如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     using System.Threading.Tasks;
    using DemoUser.Models;
    using Microsoft.AspNetCore.Identity;

    namespace DemoUser.Infrastructure
    {
    public class CustomUserValidator
    {
    public Task<IdentityResult> ValidateAsync(UserManager<AppUser> manager,
    AppUser user) {
    if (user.Email.ToLower().EndsWith("test@163.com")) {
    return Task.FromResult(IdentityResult.Success);
    } else {
    return Task.FromResult(IdentityResult.Failed(new IdentityError {
    Code = "EmailError",
    Description = "仅仅可以包含test@163.com后缀"
    }));
    } }
    }
    }
    • 我们在Startup类中的ConfigureServices 注入我们自定义的CustomUserValidator类,代码如下:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      public void ConfigureServices(IServiceCollection services)
      {
      //注入自定义用户名验证类
      services.AddTransient<IUserValidator<AppUser>,
      CustomUserValidator>();

      //注入自定义密码验证类
      services.AddTransient<IPasswordValidator<AppUser>,
      CustomPasswordValidator>();

      services.AddDbContext<AppIdentityDbContext>(options =>
      options.UseSqlServer(
      Configuration["Data:AppStoreIdentity:ConnectionString"]));
      //配置
      services.AddIdentity<AppUser, IdentityRole>(opts => {
      //配置用户名验证规则
      opts.User.RequireUniqueEmail = true;
      opts.User.AllowedUserNameCharacters = "testabc";
      //配置密码强度
      opts.Password.RequiredLength = 6;
      opts.Password.RequireNonAlphanumeric = false;
      opts.Password.RequireLowercase = false;
      opts.Password.RequireUppercase = false;
      opts.Password.RequireDigit = false;
      }).AddEntityFrameworkStores<AppIdentityDbContext>()
      .AddDefaultTokenProviders();
      services.AddMvc();
      }

    这样我们就成功替换掉内置的用户验证类了。重新运行程序就可以了。

    后记

    这篇介绍了IUserValidator的使用方法,以及如何自定义我们自己的规则。从下一篇开始我打算开始介绍如何用Identity来对用户进行验证和授权。
    github地址 对应分支f5

文章目录
  1. 1. 主题
  2. 2. 使用内置的IUserValidator来定义用户户名的规则
  3. 3. 自定义用户验证
  • IUserValidator接口的源代码
  • 实现IUserValidator 接口
    1. 1. 后记
  • |