ASP.NET Core 简介 IdentityIntroduction to Identity on ASP.NET Core

作者:Rick AndersonBy Rick Anderson

ASP.NET Core Identity:ASP.NET Core Identity:

  • 是一个 API,它支持用户界面) 登录功能 (UI。Is an API that supports user interface (UI) login functionality.
  • 管理用户、密码、配置文件数据、角色、声明、令牌、电子邮件确认等。Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.

用户可以使用存储在中的登录信息创建一个帐户, Identity 也可以使用外部登录提供程序。Users can create an account with the login information stored in Identity or they can use an external login provider. 支持的外部登录提供程序包括Facebook、Google、Microsoft 帐户和 TwitterSupported external login providers include Facebook, Google, Microsoft Account, and Twitter.

有关如何全局要求所有用户进行身份验证的信息,请参阅需要经过身份验证的用户For information on how to globally require all users to be authenticated, see Require authenticated users.

GitHub 上提供了 Identity 源代码The Identity source code is available on GitHub. 基架 Identity 并查看生成的文件以查看与的模板交互 Identity 。Scaffold Identity and view the generated files to review the template interaction with Identity.

Identity通常使用 SQL Server 数据库配置以存储用户名、密码和配置文件数据。Identity is typically configured using a SQL Server database to store user names, passwords, and profile data. 另外,还可以使用另一个永久性存储,例如 Azure 表存储。Alternatively, another persistent store can be used, for example, Azure Table Storage.

在本主题中,你将了解如何使用 Identity 注册、登录和注销用户。In this topic, you learn how to use Identity to register, log in, and log out a user. 注意:这些模板将用户的用户名和电子邮件视为相同。Note: the templates treat username and email as the same for users. 有关创建使用的应用程序的更多详细说明 Identity ,请参阅后续步骤For more detailed instructions about creating apps that use Identity, see Next Steps.

Microsoft 标识平台是:Microsoft identity platform is:

  • ) 开发人员平台 Azure AD Azure Active Directory (的演变。An evolution of the Azure Active Directory (Azure AD) developer platform.
  • 与 ASP.NET Core 无关 Identity 。Unrelated to ASP.NET Core Identity.

ASP.NET Core 标识将用户界面 (UI) 登录功能添加到 ASP.NET Core Web 应用。ASP.NET Core Identity adds user interface (UI) login functionality to ASP.NET Core web apps. 若要保护 Web API 和 SPA,请使用以下项之一:To secure web APIs and SPAs, use one of the following:

IdentityServer4 是适用于 ASP.NET Core 的 OpenID Connect 和 OAuth 2.0 框架。IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core. IdentityServer4 支持以下安全功能:IdentityServer4 enables the following security features:

  • 身份验证即服务 (AaaS)Authentication as a Service (AaaS)
  • 跨多个应用程序类型的单一登录/注销 (SSO)Single sign-on/off (SSO) over multiple application types
  • API 的访问控制Access control for APIs
  • Federation GatewayFederation Gateway

有关详细信息,请参阅欢迎使用 IdentityServer4For more information, see Welcome to IdentityServer4.

查看或下载示例代码 (如何下载) 。View or download the sample code (how to download).

创建具有身份验证的 Web 应用Create a Web app with authentication

使用单独的用户帐户创建 ASP.NET Core Web 应用程序项目。Create an ASP.NET Core Web Application project with Individual User Accounts.

  • 选择 "文件" " > 新建 > 项目"。Select File > New > Project.
  • 选择“ASP.NET Core Web 应用程序”。Select ASP.NET Core Web Application. 将项目命名为WebApp1 ,使其命名空间与项目下载相同。Name the project WebApp1 to have the same namespace as the project download. 单击“确定”。Click OK.
  • 选择 ASP.NET Core Web 应用程序,然后选择 "更改身份验证"。Select an ASP.NET Core Web Application, then select Change Authentication.
  • 选择单个用户帐户,然后单击 "确定"Select Individual User Accounts and click OK.

生成的项目 Razor 以类库形式提供ASP.NET Core Identity The generated project provides ASP.NET Core Identity as a Razor Class Library. 类库 Identity Razor 公开的终结点 IdentityThe Identity Razor Class Library exposes endpoints with the Identity area. 例如:For example:

  • /Identity/Account/Login/Identity/Account/Login
  • /Identity/Account/Logout/Identity/Account/Logout
  • /Identity/Account/Manage/Identity/Account/Manage

应用迁移Apply migrations

应用迁移以初始化数据库。Apply the migrations to initialize the database.

在包管理器控制台中运行以下命令 (PMC) :Run the following command in the Package Manager Console (PMC):

PM> Update-Database

测试注册和登录Test Register and Login

运行应用并注册用户。Run the app and register a user. 根据屏幕大小,你可能需要选择 "导航" 切换按钮以查看 "寄存器" 和 "登录" 链接。Depending on your screen size, you might need to select the navigation toggle button to see the Register and Login links.

查看标识数据库View the Identity database

  • 从 "视图" 菜单中选择 " SQL Server 对象资源管理器" (SSOX)。From the View menu, select SQL Server Object Explorer (SSOX).
  • 导航到 (localdb) MSSQLLocalDB (SQL Server 13)Navigate to (localdb)MSSQLLocalDB(SQL Server 13). 右键单击 " dbo"。 > 查看数据AspNetUsers:Right-click on dbo.AspNetUsers > View Data:

SQL Server 对象资源管理器中的 AspNetUsers 表上的上下文菜单

配置 Identity 服务Configure Identity services

中添加了服务 ConfigureServicesServices are added in ConfigureServices. 典型模式是调用所有 Add{Service} 方法,然后调用所有 services.Configure{Service} 方法。The typical pattern is to call all the Add{Service} methods, and then call all the services.Configure{Service} methods.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
     // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // 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;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

前面突出显示的代码 Identity 用默认选项值进行配置。The preceding highlighted code configures Identity with default option values. 服务通过依赖关系注入提供给应用程序。Services are made available to the app through dependency injection.

Identity通过调用启用 UseAuthenticationIdentity is enabled by calling UseAuthentication. UseAuthentication将身份验证中间件添加到请求管道。UseAuthentication adds authentication middleware to the request pipeline.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

模板生成的应用不使用授权The template-generated app doesn't use authorization. app.UseAuthorization包括,以确保在应用添加授权时,按正确的顺序添加。app.UseAuthorization is included to ensure it's added in the correct order should the app add authorization. UseRoutingUseAuthenticationUseAuthorizationUseEndpoints 必须按前面的代码中所示的顺序调用。UseRouting, UseAuthentication, UseAuthorization, and UseEndpoints must be called in the order shown in the preceding code.

有关和的详细 IdentityOptions 信息 Startup ,请参阅 IdentityOptions应用程序启动For more information on IdentityOptions and Startup, see IdentityOptions and Application Startup.

基架注册、登录、注销和 RegisterConfirmationScaffold Register, Login, LogOut, and RegisterConfirmation

添加 RegisterLoginLogOutRegisterConfirmation 文件。Add the Register, Login, LogOut, and RegisterConfirmation files. 基架标识置于 Razor 具有授权说明的项目中,以生成本部分中所示的代码。Follow the Scaffold identity into a Razor project with authorization instructions to generate the code shown in this section.

检查注册Examine Register

当用户单击页面上的 "注册" 按钮时 Register ,将 RegisterModel.OnPostAsync 调用该操作。When a user clicks the Register button on the Register page, the RegisterModel.OnPostAsync action is invoked. 用户由CreateAsync在对象上创建 _userManagerThe user is created by CreateAsync on the _userManager object:

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

禁用默认帐户验证Disable default account verification

使用默认模板时,会将用户重定向到用户 Account.RegisterConfirmation 可以在其中选择要确认帐户的链接。With the default templates, the user is redirected to the Account.RegisterConfirmation where they can select a link to have the account confirmed. 默认值 Account.RegisterConfirmation 用于测试,应在生产应用中禁用自动帐户验证。The default Account.RegisterConfirmation is used only for testing, automatic account verification should be disabled in a production app.

若要在注册时要求确认帐户并阻止立即登录,请 DisplayConfirmAccountLink = false/Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs中设置:To require a confirmed account and prevent immediate login at registration, set DisplayConfirmAccountLink = false in /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs:

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

登录Log in

当出现以下情况时,将显示登录窗体:The Login form is displayed when:

  • 选择 "登录" 链接。The Log in link is selected.
  • 用户尝试访问他们无权访问的受限制的页面,未经系统的身份验证。A user attempts to access a restricted page that they aren't authorized to access or when they haven't been authenticated by the system.

提交登录页上的窗体时,将 OnPostAsync 调用该操作。When the form on the Login page is submitted, the OnPostAsync action is called. PasswordSignInAsync_signInManager 对象调用。PasswordSignInAsync is called on the _signInManager object.

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

    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: true);
        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();
}

有关如何做出授权决策的信息,请参阅 ASP.NET Core 中的授权简介For information on how to make authorization decisions, see ASP.NET Core 中的授权简介.

注销Log out

"注销" 链接将调用该 LogoutModel.OnPost 操作。The Log out link invokes the LogoutModel.OnPost action.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

在前面的代码中,代码 return RedirectToPage(); 需要是重定向,以便浏览器执行新请求并更新用户的标识。In the preceding code, the code return RedirectToPage(); needs to be a redirect so that the browser performs a new request and the identity for the user gets updated.

SignOutAsync清除存储在中的用户声明 cookie 。SignOutAsync clears the user's claims stored in a cookie.

Post 在Pages/Shared/_LoginPartial 中指定。 cshtmlPost is specified in the Pages/Shared/_LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

考试IdentityTest Identity

默认 web 项目模板允许匿名访问主页。The default web project templates allow anonymous access to the home pages. 若要测试 Identity ,请添加 [Authorize]To test Identity, add [Authorize]:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

如果已登录,请注销。运行应用并选择 "隐私" 链接。If you are signed in, sign out. Run the app and select the Privacy link. 将被重定向到登录页。You are redirected to the login page.

浏览IdentityExplore Identity

Identity了解更多详细信息:To explore Identity in more detail:

Identity组分Identity Components

所有 Identity 相关的 NuGet 包都包含在ASP.NET Core 共享框架中。All the Identity-dependent NuGet packages are included in the ASP.NET Core shared framework.

的主包为 Identity AspNetCore。 Identity The primary package for Identity is Microsoft.AspNetCore.Identity. 此程序包包含用于 ASP.NET Core 的核心接口集 Identity ,由提供 Microsoft.AspNetCore.Identity.EntityFrameworkCoreThis package contains the core set of interfaces for ASP.NET Core Identity, and is included by Microsoft.AspNetCore.Identity.EntityFrameworkCore.

迁移到 ASP.NET CoreIdentityMigrating to ASP.NET Core Identity

有关迁移现有存储的详细信息和指南 Identity ,请参阅迁移身份验证 Identity 和For more information and guidance on migrating your existing Identity store, see Migrate Authentication and Identity.

设置密码强度Setting password strength

有关设置最小密码要求的示例,请参阅配置See Configuration for a sample that sets the minimum password requirements.

AddDefault Identity 并添加IdentityAddDefaultIdentity and AddIdentity

AddDefaultIdentity是在 ASP.NET Core 2.1 中引入的。AddDefaultIdentity was introduced in ASP.NET Core 2.1. 调用 AddDefaultIdentity 类似于调用以下内容:Calling AddDefaultIdentity is similar to calling the following:

有关详细信息,请参阅AddDefault Identity 源See AddDefaultIdentity source for more information.

禁止发布静态 Identity 资产Prevent publish of static Identity assets

若要防止将静态 Identity 资产发布 (用于 UI) 的用户的样式和 JavaScript 文件 Identity ,请将以下 ResolveStaticWebAssetsInputsDependsOn 属性和目标添加 RemoveIdentityAssets 到应用的项目文件中:To prevent publishing static Identity assets (stylesheets and JavaScript files for Identity UI) to the web root, add the following ResolveStaticWebAssetsInputsDependsOn property and RemoveIdentityAssets target to the app's project file:

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

后续步骤Next Steps

作者:Rick AndersonBy Rick Anderson

ASP.NET Core Identity 是将登录功能添加到 ASP.NET Core 应用的成员资格系统。ASP.NET Core Identity is a membership system that adds login functionality to ASP.NET Core apps. 用户可以使用存储在中的登录信息创建一个帐户, Identity 也可以使用外部登录提供程序。Users can create an account with the login information stored in Identity or they can use an external login provider. 支持的外部登录提供程序包括Facebook、Google、Microsoft 帐户和 TwitterSupported external login providers include Facebook, Google, Microsoft Account, and Twitter.

Identity可以使用 SQL Server 数据库配置以存储用户名、密码和配置文件数据。Identity can be configured using a SQL Server database to store user names, passwords, and profile data. 另外,还可以使用另一个永久性存储,例如 Azure 表存储。Alternatively, another persistent store can be used, for example, Azure Table Storage.

查看或下载示例代码 (如何下载) 。View or download the sample code (how to download).

在本主题中,你将了解如何使用 Identity 注册、登录和注销用户。In this topic, you learn how to use Identity to register, log in, and log out a user. 有关创建使用的应用程序的更多详细说明 Identity ,请参阅本文末尾的后续步骤部分。For more detailed instructions about creating apps that use Identity, see the Next Steps section at the end of this article.

AddDefault Identity 并添加IdentityAddDefaultIdentity and AddIdentity

AddDefaultIdentity是在 ASP.NET Core 2.1 中引入的。AddDefaultIdentity was introduced in ASP.NET Core 2.1. 调用 AddDefaultIdentity 类似于调用以下内容:Calling AddDefaultIdentity is similar to calling the following:

有关详细信息,请参阅AddDefault Identity 源See AddDefaultIdentity source for more information.

创建具有身份验证的 Web 应用Create a Web app with authentication

使用单独的用户帐户创建 ASP.NET Core Web 应用程序项目。Create an ASP.NET Core Web Application project with Individual User Accounts.

  • 选择 "文件" " > 新建 > 项目"。Select File > New > Project.
  • 选择“ASP.NET Core Web 应用程序”。Select ASP.NET Core Web Application. 将项目命名为WebApp1 ,使其命名空间与项目下载相同。Name the project WebApp1 to have the same namespace as the project download. 单击“确定”。Click OK.
  • 选择 ASP.NET Core Web 应用程序,然后选择 "更改身份验证"。Select an ASP.NET Core Web Application, then select Change Authentication.
  • 选择单个用户帐户,然后单击 "确定"Select Individual User Accounts and click OK.

生成的项目 Razor 以类库形式提供ASP.NET Core Identity The generated project provides ASP.NET Core Identity as a Razor Class Library. 类库 Identity Razor 公开的终结点 IdentityThe Identity Razor Class Library exposes endpoints with the Identity area. 例如:For example:

  • /Identity/Account/Login/Identity/Account/Login
  • /Identity/Account/Logout/Identity/Account/Logout
  • /Identity/Account/Manage/Identity/Account/Manage

应用迁移Apply migrations

应用迁移以初始化数据库。Apply the migrations to initialize the database.

在包管理器控制台中运行以下命令 (PMC) :Run the following command in the Package Manager Console (PMC):

Update-Database

测试注册和登录Test Register and Login

运行应用并注册用户。Run the app and register a user. 根据屏幕大小,你可能需要选择 "导航" 切换按钮以查看 "寄存器" 和 "登录" 链接。Depending on your screen size, you might need to select the navigation toggle button to see the Register and Login links.

查看标识数据库View the Identity database

  • 从 "视图" 菜单中选择 " SQL Server 对象资源管理器" (SSOX)。From the View menu, select SQL Server Object Explorer (SSOX).
  • 导航到 (localdb) MSSQLLocalDB (SQL Server 13)Navigate to (localdb)MSSQLLocalDB(SQL Server 13). 右键单击 " dbo"。 > 查看数据AspNetUsers:Right-click on dbo.AspNetUsers > View Data:

SQL Server 对象资源管理器中的 AspNetUsers 表上的上下文菜单

配置 Identity 服务Configure Identity services

中添加了服务 ConfigureServicesServices are added in ConfigureServices. 典型模式是调用所有 Add{Service} 方法,然后调用所有 services.Configure{Service} 方法。The typical pattern is to call all the Add{Service} methods, and then call all the services.Configure{Service} methods.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<CookiePolicyOptions>(options =>
    {
        options.CheckConsentNeeded = context => true;
        options.MinimumSameSitePolicy = SameSiteMode.None;
    });

    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddDefaultUI(UIFramework.Bootstrap4)
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.Configure<IdentityOptions>(options =>
    {
        // 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;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });

    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

前面的代码 Identity 用默认选项值进行配置。The preceding code configures Identity with default option values. 服务通过依赖关系注入提供给应用程序。Services are made available to the app through dependency injection.

Identity通过调用UseAuthentication启用。Identity is enabled by calling UseAuthentication. UseAuthentication将身份验证中间件添加到请求管道。UseAuthentication adds authentication middleware to the request pipeline.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

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

    app.UseAuthentication();

    app.UseMvc();
}

有关详细信息,请参阅 Identity Options 类应用程序启动For more information, see the IdentityOptions Class and Application Startup.

基架注册、登录和注销Scaffold Register, Login, and LogOut

基架标识置于 Razor 具有授权说明的项目中,以生成本部分中所示的代码。Follow the Scaffold identity into a Razor project with authorization instructions to generate the code shown in this section.

添加注册、登录和注销文件。Add the Register, Login, and LogOut files.

检查注册Examine Register

当用户单击 "注册" 链接时,将 RegisterModel.OnPostAsync 调用该操作。When a user clicks the Register link, the RegisterModel.OnPostAsync action is invoked. 用户由CreateAsync在对象上创建 _userManagerThe user is created by CreateAsync on the _userManager object:

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            await _signInManager.SignInAsync(user, isPersistent: false);
            return LocalRedirect(returnUrl);
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

如果用户已成功创建,则对的调用会登录该用户 _signInManager.SignInAsyncIf the user was created successfully, the user is logged in by the call to _signInManager.SignInAsync.

注意: 请参阅帐户确认以了解在注册时要阻止立即登录的步骤。Note: See account confirmation for steps to prevent immediate login at registration.

登录Log in

当出现以下情况时,将显示登录窗体:The Login form is displayed when:

  • 选择 "登录" 链接。The Log in link is selected.
  • 用户尝试访问他们无权访问的受限制的页面,未经系统的身份验证。A user attempts to access a restricted page that they aren't authorized to access or when they haven't been authenticated by the system.

提交登录页上的窗体时,将 OnPostAsync 调用该操作。When the form on the Login page is submitted, the OnPostAsync action is called. PasswordSignInAsync_signInManager 对象调用。PasswordSignInAsync is called on the _signInManager object.

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

    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: true);
        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();
}

有关如何做出授权决策的信息,请参阅 ASP.NET Core 中的授权简介For information on how to make authorization decisions, see ASP.NET Core 中的授权简介.

注销Log out

"注销" 链接将调用该 LogoutModel.OnPost 操作。The Log out link invokes the LogoutModel.OnPost action.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                // This needs to be a redirect so that the browser performs a new
                // request and the identity for the user gets updated.
                return RedirectToPage();
            }
        }
    }
}

SignOutAsync清除存储在中的用户声明 cookie 。SignOutAsync clears the user's claims stored in a cookie.

Post 在Pages/Shared/_LoginPartial 中指定。 cshtmlPost is specified in the Pages/Shared/_LoginPartial.cshtml:

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
    @if (SignInManager.IsSignedIn(User))
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity"
               asp-page="/Account/Manage/Index"
               title="Manage">Hello@User.Identity.Name!</a>
        </li>
        <li class="nav-item">
            <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                   asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                   method="post">
                <button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
            </form>
        </li>
    }
    else
    {
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
        </li>
    }
</ul>


考试IdentityTest Identity

默认 web 项目模板允许匿名访问主页。The default web project templates allow anonymous access to the home pages. 若要进行测试 Identity ,请将添加 [Authorize] 到 "隐私" 页。To test Identity, add [Authorize] to the Privacy page.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        public void OnGet()
        {
        }
    }
}

如果已登录,请注销。运行应用并选择 "隐私" 链接。If you are signed in, sign out. Run the app and select the Privacy link. 将被重定向到登录页。You are redirected to the login page.

浏览IdentityExplore Identity

Identity了解更多详细信息:To explore Identity in more detail:

Identity组分Identity Components

所有 Identity 相关 NuGet 包都包含在AspNetCore 元包中。All the Identity dependent NuGet packages are included in the Microsoft.AspNetCore.App metapackage.

的主包为 Identity AspNetCore。 Identity The primary package for Identity is Microsoft.AspNetCore.Identity. 此程序包包含用于 ASP.NET Core 的核心接口集 Identity ,由提供 Microsoft.AspNetCore.Identity.EntityFrameworkCoreThis package contains the core set of interfaces for ASP.NET Core Identity, and is included by Microsoft.AspNetCore.Identity.EntityFrameworkCore.

迁移到 ASP.NET CoreIdentityMigrating to ASP.NET Core Identity

有关迁移现有存储的详细信息和指南 Identity ,请参阅迁移身份验证 Identity 和For more information and guidance on migrating your existing Identity store, see Migrate Authentication and Identity.

设置密码强度Setting password strength

有关设置最小密码要求的示例,请参阅配置See Configuration for a sample that sets the minimum password requirements.

后续步骤Next Steps