配置 ASP.NET Core Identity

ASP.NET Core Identity使用密码策略、锁定和cookie配置等设置的默认值。 可以在应用程序启动时重写这些设置。

Identity 选项

IdentityOptions 类表示可用于配置 Identity 系统的选项。 IdentityOptions 必须在调用 AddIdentityAddDefaultIdentity 之后设置。

声明 Identity

IdentityOptions.ClaimsIdentity 使用下表所示的属性指定 ClaimsIdentityOptions

属性 说明 默认
RoleClaimType 获取或设置用于角色声明的声明类型。 ClaimTypes.Role
SecurityStampClaimType 获取或设置用于安全戳声明的声明类型。 AspNet.Identity.SecurityStamp
UserIdClaimType 获取或设置用于用户标识符声明的声明类型。 ClaimTypes.NameIdentifier
UserNameClaimType 获取或设置用于用户名声明的声明类型。 ClaimTypes.Name

锁定

PasswordSignInAsync方法设置锁定:

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl ??= Url.Content("~/");

    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
             Input.Password, Input.RememberMe,
             lockoutOnFailure: false);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

上述代码基于LoginIdentity模板

Program.cs 中设置锁定选项:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options =>
                                       options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Default Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapRazorPages();

app.Run();

上述代码将 IdentityOptions LockoutOptions 设置为默认值。

身份验证成功后,将重置失败访问尝试计数并重置时钟。

IdentityOptions.Lockout使用表中所示的属性指定LockoutOptions

属性 说明 默认
AllowedForNewUsers 确定是否可以锁定新用户。 true
DefaultLockoutTimeSpan 发生锁定时用户被锁定的时长。 5 分钟
MaxFailedAccessAttempts 启用锁定后,在用户被锁定之前失败的访问尝试次数。 5

密码

默认情况下,Identity 要求密码包含大写字符、小写字符、数字和非字母数字字符。 密码长度必须至少为六个字符。

使用以下各项配置密码:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using RPauth.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options =>
                                options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Default Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;
});

var app = builder.Build();

// Remaining code removed for brevity.

IdentityOptions.Password使用表中所示的属性指定PasswordOptions

属性 说明 默认
RequireDigit 密码中需要有一个 0-9 之间的数字。 true
RequiredLength 密码的最小长度。 6
RequireLowercase 密码中需要有小写字符。 true
RequireNonAlphanumeric 密码中需要有非字母数字字符。 true
RequiredUniqueChars 仅适用于 ASP.NET Core 2.0 或更高版本。

密码中需要有非重复字符数。
1
RequireUppercase 密码中需要有大写字符。 true

登录

以下代码将 SignIn 设置设为默认值:

builder.Services.Configure<IdentityOptions>(options =>
{
    // Default SignIn settings.
    options.SignIn.RequireConfirmedEmail = false;
    options.SignIn.RequireConfirmedPhoneNumber = false;
});

IdentityOptions.SignIn使用表中所示的属性指定SignInOptions

属性 说明 默认
RequireConfirmedEmail 需要已确认的电子邮件才能登录。 false
RequireConfirmedPhoneNumber 需要已确认的电话号码才能登录。 false

令牌

IdentityOptions.Tokens使用表中所示的属性指定TokenOptions

属性 说明
AuthenticatorTokenProvider 获取或设置 AuthenticatorTokenProvider,用于通过验证器验证双重登录。
ChangeEmailTokenProvider 获取或设置 ChangeEmailTokenProvider,用于生成在电子邮件更改确认电子邮件中使用的令牌。
ChangePhoneNumberTokenProvider 获取或设置 ChangePhoneNumberTokenProvider,用于生成更改电话号码时使用的令牌。
EmailConfirmationTokenProvider 获取或设置令牌提供程序,用于生成在帐户确认电子邮件中使用的令牌。
PasswordResetTokenProvider 获取或设置IUserTwoFactorTokenProvider<TUser>,用于生成在密码重置电子邮件中使用的令牌。
ProviderMap 用于构造用户令牌提供程序,并将密钥用作提供程序的名称。

用户

builder.Services.Configure<IdentityOptions>(options =>
{
    // Default User settings.
    options.User.AllowedUserNameCharacters =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;

});

IdentityOptions.User使用表中所示的属性指定UserOptions

属性 说明 默认
AllowedUserNameCharacters 用户名中允许使用的字符。 abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
.'. .
RequireUniqueEmail 要求每个用户都有唯一的电子邮件。 false

Program.cs 中配置应用 cookie。 必须在调用 AddIdentityAddDefaultIdentity 之后调用 ConfigureApplicationCookie

builder.Services.ConfigureApplicationCookie(options =>
{
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.Cookie.Name = "YourAppCookieName";
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
    options.LoginPath = "/Identity/Account/Login";
    // ReturnUrlParameter requires 
    //using Microsoft.AspNetCore.Authentication.Cookies;
    options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
    options.SlidingExpiration = true;
});

有关详细信息,请参阅 CookieAuthenticationOptions

密码 Hasher 选项

PasswordHasherOptions 获取和设置密码哈希选项。

选项 说明
CompatibilityMode 对新密码进行哈希处理时所使用的兼容模式。 默认为 IdentityV3。 哈希密码的第一个字节称为格式标记,指定用于对密码进行哈希处理的哈希算法版本。 根据哈希验证密码时,VerifyHashedPassword 方法会根据第一个字节选择正确的算法。 无论使用哪个版本的算法对密码进行哈希处理,客户端都能够进行身份验证。 设置兼容模式会影响新密码的哈希处理。
IterationCount 使用 PBKDF2 对密码进行哈希处理时所使用的迭代次数。 此值仅在 CompatibilityMode 设置为 IdentityV3 时使用。 此值必须是正整数,默认为 100000

以下示例在 Program.cs 中将 IterationCount 设置为 12000

// using Microsoft.AspNetCore.Identity;

builder.Services.Configure<PasswordHasherOptions>(option =>
{
    option.IterationCount = 12000;
});

要求全局范围内的所有用户都进行身份验证

有关如何全局要求所有用户进行身份验证的信息,请参阅需要通过身份验证的用户

ISecurityStampValidator 和 SignOut 随处可见

应用需要重新生成用户ClaimsPrincipal以响应涉及安全敏感操作的事件。 例如,ClaimsPrincipal在加入角色、更改密码或其他安全敏感事件中,应重新生成。 Identity使用ISecurityStampValidator接口重新生成ClaimsPrincipal。 Identity的默认实现向主要的应用程序cookie和双因素cookie注册SecurityStampValidator。 验证程序会挂钩到要调用到Identity的每个cookie的OnValidatePrincipal事件,从而验证用户的安全戳声明是否与cookie中存储的内容保持不变。 验证程序定期调用。 调用间隔是在过于频繁和不够频繁地访问数据存储之间进行权衡。 使用较长的间隔进行检查会导致声明过时。 调用 userManager.UpdateSecurityStampAsync(user) 以迫使在现有下次检查时失效。 更改密码或添加登录后,大多数IdentityUI 帐户和管理页面都会调用userManager.UpdateSecurityStampAsync(user)。 应用可以调用userManager.UpdateSecurityStampAsync(user)以实现随处注销操作。

更改验证间隔显示在以下突出显示的代码中:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebClaimsPrincipal.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") 
    ?? throw new InvalidOperationException("'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => 
options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// Force Identity's security stamp to be validated every minute.
builder.Services.Configure<SecurityStampValidatorOptions>(o => 
                   o.ValidationInterval = TimeSpan.FromMinutes(1));

builder.Services.AddRazorPages();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapRazorPages();

app.Run();

ASP.NET Core Identity使用密码策略、锁定和cookie配置等设置的默认值。 可在 Startup 类中替代这些设置。

Identity 选项

IdentityOptions 类表示可用于配置 Identity 系统的选项。 IdentityOptions 必须在调用 AddIdentityAddDefaultIdentity 之后设置。

声明 Identity

IdentityOptions.ClaimsIdentity 使用下表所示的属性指定 ClaimsIdentityOptions

属性 说明 默认
RoleClaimType 获取或设置用于角色声明的声明类型。 ClaimTypes.Role
SecurityStampClaimType 获取或设置用于安全戳声明的声明类型。 AspNet.Identity.SecurityStamp
UserIdClaimType 获取或设置用于用户标识符声明的声明类型。 ClaimTypes.NameIdentifier
UserNameClaimType 获取或设置用于用户名声明的声明类型。 ClaimTypes.Name

锁定

PasswordSignInAsync方法设置锁定:

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        var result = await _signInManager.PasswordSignInAsync(Input.Email, 
            Input.Password, Input.RememberMe, 
            lockoutOnFailure: false);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl,
                Input.RememberMe });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

    // If we got this far, something failed, redisplay form
    return Page();
}

上述代码基于 LoginIdentity 模板。

StartUp.ConfigureServices 中设置锁定选项:

services.Configure<IdentityOptions>(options =>
{
    // Default Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;
});

上述代码将 IdentityOptions LockoutOptions 设置为默认值。

身份验证成功后,将重置失败访问尝试计数并重置时钟。

IdentityOptions.Lockout使用表中所示的属性指定LockoutOptions

属性 说明 默认
AllowedForNewUsers 确定是否可以锁定新用户。 true
DefaultLockoutTimeSpan 发生锁定时用户被锁定的时长。 5 分钟
MaxFailedAccessAttempts 启用锁定后,在用户被锁定之前失败的访问尝试次数。 5

密码

默认情况下,Identity 要求密码包含大写字符、小写字符、数字和非字母数字字符。 密码长度必须至少为六个字符。

使用以下各项配置密码:

services.Configure<IdentityOptions>(options =>
{
    // Default Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;
});

IdentityOptions.Password使用表中所示的属性指定PasswordOptions

属性 说明 默认
RequireDigit 密码中需要有一个 0-9 之间的数字。 true
RequiredLength 密码的最小长度。 6
RequireLowercase 密码中需要有小写字符。 true
RequireNonAlphanumeric 密码中需要有非字母数字字符。 true
RequiredUniqueChars 仅适用于 ASP.NET Core 2.0 或更高版本。

密码中需要有非重复字符数。
1
RequireUppercase 密码中需要有大写字符。 true

登录

以下代码将 SignIn 设置设为默认值:

services.Configure<IdentityOptions>(options =>
{
    // Default SignIn settings.
    options.SignIn.RequireConfirmedEmail = false;
    options.SignIn.RequireConfirmedPhoneNumber = false;
});

IdentityOptions.SignIn使用表中所示的属性指定SignInOptions

属性 说明 默认
RequireConfirmedEmail 需要已确认的电子邮件才能登录。 false
RequireConfirmedPhoneNumber 需要已确认的电话号码才能登录。 false

令牌

IdentityOptions.Tokens使用表中所示的属性指定TokenOptions

属性 说明
AuthenticatorTokenProvider 获取或设置 AuthenticatorTokenProvider,用于通过验证器验证双重登录。
ChangeEmailTokenProvider 获取或设置 ChangeEmailTokenProvider,用于生成在电子邮件更改确认电子邮件中使用的令牌。
ChangePhoneNumberTokenProvider 获取或设置 ChangePhoneNumberTokenProvider,用于生成更改电话号码时使用的令牌。
EmailConfirmationTokenProvider 获取或设置令牌提供程序,用于生成在帐户确认电子邮件中使用的令牌。
PasswordResetTokenProvider 获取或设置IUserTwoFactorTokenProvider<TUser>,用于生成在密码重置电子邮件中使用的令牌。
ProviderMap 用于构造用户令牌提供程序,并将密钥用作提供程序的名称。

用户

services.Configure<IdentityOptions>(options =>
{
    // Default User settings.
    options.User.AllowedUserNameCharacters =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;

});

IdentityOptions.User使用表中所示的属性指定UserOptions

属性 说明 默认
AllowedUserNameCharacters 用户名中允许使用的字符。 abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
0123456789
.'. .
RequireUniqueEmail 要求每个用户都有唯一的电子邮件。 false

Startup.ConfigureServices 中配置应用 cookie。 必须在调用 AddIdentityAddDefaultIdentity 之后调用 ConfigureApplicationCookie

services.ConfigureApplicationCookie(options =>
{
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.Cookie.Name = "YourAppCookieName";
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
    options.LoginPath = "/Identity/Account/Login";
    // ReturnUrlParameter requires 
    //using Microsoft.AspNetCore.Authentication.Cookies;
    options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
    options.SlidingExpiration = true;
});

有关详细信息,请参阅 CookieAuthenticationOptions

密码 Hasher 选项

PasswordHasherOptions 获取和设置密码哈希选项。

选项 说明
CompatibilityMode 对新密码进行哈希处理时所使用的兼容模式。 默认为 IdentityV3。 哈希密码的第一个字节称为格式标记,指定用于对密码进行哈希处理的哈希算法版本。 根据哈希验证密码时,VerifyHashedPassword 方法会根据第一个字节选择正确的算法。 无论使用哪个版本的算法对密码进行哈希处理,客户端都能够进行身份验证。 设置兼容模式会影响新密码的哈希处理。
IterationCount 使用 PBKDF2 对密码进行哈希处理时所使用的迭代次数。 此值仅在 CompatibilityMode 设置为 IdentityV3 时使用。 此值必须是正整数,默认为 10000

以下示例在 Startup.ConfigureServices 中将 IterationCount 设置为 12000

// using Microsoft.AspNetCore.Identity;

services.Configure<PasswordHasherOptions>(option =>
{
    option.IterationCount = 12000;
});

要求全局范围内的所有用户都进行身份验证

有关如何全局要求所有用户进行身份验证的信息,请参阅需要通过身份验证的用户