练习 - 配置标识支持

已完成

标识无需任何自定义,开箱即可使用。 在本单元中,向现有的 ASP.NET Core Razor Pages 项目添加标识。

获取并打开初学者项目

注意

如果想要使用 GitHub Codespaces 中的 .devcontainer,请导航到 MicrosoftDocs/mslearn-secure-aspnet-core-identity 存储库的 codespace。 使用 main 分支创建新的代码空间,然后跳到步骤 3。

  1. 在终端窗口中,运行以下命令以获取初学者项目:

    git clone https://github.com/MicrosoftDocs/mslearn-secure-aspnet-core-identity
    
  2. 切换到源代码目录并启动 Visual Studio Code:

    cd mslearn-secure-aspnet-core-identity
    code .
    

    Visual Studio Code 将打开。 接受安装建议的扩展的任何提示,或者如果要使用“.devcontainer”,请选择“在容器中重新打开”。

    提示

    如果错过了“在容器中重新打开”提示,请按 Ctrl+Shift+P 打开命令面板,然后搜索并选择“开发容器: 在容器中重新打开”

  3. 在项目加载(在本地或容器中)后,按 Ctrl+Shift+` 打开新的终端窗格

  4. 在新终端窗格中,将位置设置为“RazorPagesPizza”目录:

    cd RazorPagesPizza
    
  5. 在“资源管理器”窗格中,展开“RazorPagesPizza”目录以查看代码。 “RazorPagesPizza”是项目目录。 继续操作时,假设本模块中讨论的所有路径都相对于此位置。

浏览应用

让我们运行应用来快速了解内容。

  1. 在终端窗格中,生成项目并运行应用:

    dotnet run
    
  2. 请注意终端输出中显示的 URL。 例如,https://localhost:7192

  3. 使用 Ctr+单击来选择 URL,从而在浏览器中打开应用

    重要

    如果在 Docker 中使用“.devcontainer”,则浏览器不会信任容器内部的 SSL 证书。 若要查看 Web 应用,必须执行下列操作之一:

    • 忽略证书错误。 如果使用 Microsoft Edge,请选择“高级”和“继续执行 localhost (不建议)”。 详细信息因浏览器而异。
    • 保存证书并将其添加到受信任的证书颁发机构。
    • 在容器中导入现有开发证书。 如需更多信息,请参阅“./devcontainer/devcontainter.json”中生成的注释。

    如果选择在容器中导入现有开发证书,容器路径“/root/.aspnet/”会公开为容器外部的“.devcontainer/persisted-data/.aspnet”。 这是为了使你方便使用。

    如果要在 GitHub Codespaces 中使用“.devcontainer”,则无需执行操作。 Codespaces 会自动处理代理 SSL 连接。

  4. 在浏览器中浏览 Web 应用。 使用标头上的链接:

    1. 导航到“披萨列表”
    2. 导航回“主页”

    请注意,你无需进行身份验证。

  5. 在终端窗格中,按 Ctrl+C 来停止应用

向项目添加 ASP.NET Core Identity

可以使用 dotnet 命令行工具添加默认标识实现。

  1. 安装 ASP.NET Core 代码基架:

    dotnet tool install dotnet-aspnet-codegenerator --version 6.0.2 --global
    

    基架是一个 .NET Core 工具,它:

    • 用于向项目添加默认标识组件。
    • 在下一单元中启用标识 UI 组件的自定义。
    • 在本模块中通过 dotnet aspnet-codegenerator 调用。
  2. 向项目添加以下 NuGet 包:

    dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design --version 6.0.2
    dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore --version 6.0.3
    dotnet add package Microsoft.AspNetCore.Identity.UI --version 6.0.3
    dotnet add package Microsoft.EntityFrameworkCore.Design --version 6.0.3
    dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 6.0.3
    

    这些包会安装基架使用的代码生成模板和依赖项。

    提示

    要查看可用的生成器,请执行以下操作:

    • 在命令 shell 中,运行 dotnet aspnet-codegenerator -h
    • 在 Visual Studio 中,右键单击解决方案资源管理器中的项目,然后选择“添加”>“新建基架项”。
  3. 使用基架向项目添加默认标识组件。 在终端中运行以下命令:

    dotnet aspnet-codegenerator identity --useDefaultUI --dbContext RazorPagesPizzaAuth
    

    在上面的命令中:

    • 标识为 identity 的生成器用于向项目添加标识框架。
    • --useDefaultUI 选项指示使用包含默认 UI 元素的 Razor 类库 (RCL)。 Bootstrap 用于设置组件的样式。
    • --dbContext 选项指定要生成的 EF Core 数据库上下文类的名称。

    以下 Areas 目录结构显示在 RazorPagesPizza 目录中:

    • Areas
      • Identity(与“Areas”显示在同一行上)
        • Data
          • RazorPagesPizzaAuth.cs
        • Pages
          • _ValidationScriptsPartial.cshtml
          • _ViewStart.cshtml

    提示

    如果 Areas 目录未自动显示在资源管理器窗格中,请在资源管理器窗格中的“MSLEARN-SECURE-ASPNET-CORE-IDENTITY”标头上选择“刷新资源管理器”按钮。

    Areas 提供了将 ASP.NET Core Web 应用分区为较小功能组的方法。

    基架还对“Program.cs”进行了以下突出显示的更改,重新设置了格式,以便阅读:

    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using RazorPagesPizza.Areas.Identity.Data;
    var builder = WebApplication.CreateBuilder(args);
    var connectionString = builder.Configuration.GetConnectionString("RazorPagesPizzaAuthConnection"); 
    builder.Services.AddDbContext<RazorPagesPizzaAuth>(options => options.UseSqlServer(connectionString)); 
    builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
          .AddEntityFrameworkStores<RazorPagesPizzaAuth>();
          
    // Add services to the container.
    builder.Services.AddRazorPages();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    app.UseAuthentication();
    app.UseAuthorization();
    
    app.MapRazorPages();
    
    app.Run();
    

    在上述代码中:

    • RazorPagesPizzaAuthConnection 连接字符串是从“appsettings.json”读取的。
    • 名为 RazorPagesPizzaAuth 的 EF Core 数据库上下文类是使用连接字符串配置的。
    • 标识服务已注册,包括默认 UI、令牌提供程序和基于 cookie 的身份验证。
      • .AddDefaultIdentity<IdentityUser> 告知标识服务使用默认用户模型。
      • lambda 表达式 options => options.SignIn.RequireConfirmedAccount = true 指定用户必须确认其电子邮件帐户。
      • .AddEntityFrameworkStores<RazorPagesPizzaAuth>() 指定标识对其数据库使用默认 Entity Framework Core 存储。 使用 RazorPagesPizzaAuthDbContext 类。
    • app.UseAuthentication(); 启用了身份验证功能。 更具体地说,向应用的 HTTP 请求处理管道添加了 ASP.NET Core 身份验证中间件的一个实例。

配置数据库连接

appsettings.json 中的 ConnectionStrings 部分应类似于以下 JSON:

"ConnectionStrings": {
    "RazorPagesPizzaAuthConnection": "Server=(localdb)\\mssqllocaldb;Database=RazorPagesPizza;Trusted_Connection=True;MultipleActiveResultSets=true"
}

默认情况下,此连接字符串指向 SQL Server Express LocalDB 实例。 如果使用的是“.devcontainer”,则必须更改连接字符串,如下所示! 保存所做更改。

"ConnectionStrings": {
    "RazorPagesPizzaAuthConnection": "Data Source=localhost;Initial Catalog=RazorPagesPizza;Integrated Security=False;User Id=sa;Password=P@ssw0rd;MultipleActiveResultSets=True"
}

这将更新连接字符串,以连接到容器内的 SQL Server 实例。

更新数据库

验证连接字符串后,可以生成并运行迁移以生成数据库。

  1. 运行以下命令以生成应用:

    dotnet build
    

    生成成功,且没有任何警告。 如果生成失败,请检查输出以获取故障排除信息。

  2. 安装 EEntity Framework Core 迁移工具:

    dotnet tool install dotnet-ef --version 6.0.3 --global
    

    迁移工具是一个 .NET 工具,它可以执行以下操作:

    • 生成名为迁移的代码,用于创建和更新支持标识实体模型的数据库。
    • 针对现有数据库执行迁移。
    • 在本模块中通过 dotnet ef 调用。
  3. 创建并运行 EF Core 迁移以更新数据库:

    dotnet ef migrations add CreateIdentitySchema
    dotnet ef database update
    

    CreateIdentitySchema EF Core 迁移应用了数据定义语言 (DDL) 更改脚本来创建支持标识的表。 例如,以下输出内容描述了由迁移生成的 CREATE TABLE 语句:

    info: Microsoft.EntityFrameworkCore.Database.Command[20101]
          Executed DbCommand (98ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
          CREATE TABLE [AspNetUsers] (
              [Id] nvarchar(450) NOT NULL,
              [UserName] nvarchar(256) NULL,
              [NormalizedUserName] nvarchar(256) NULL,
              [Email] nvarchar(256) NULL,
              [NormalizedEmail] nvarchar(256) NULL,
              [EmailConfirmed] bit NOT NULL,
              [PasswordHash] nvarchar(max) NULL,
              [SecurityStamp] nvarchar(max) NULL,
              [ConcurrencyStamp] nvarchar(max) NULL,
              [PhoneNumber] nvarchar(max) NULL,
              [PhoneNumberConfirmed] bit NOT NULL,
              [TwoFactorEnabled] bit NOT NULL,
              [LockoutEnd] datetimeoffset NULL,
              [LockoutEnabled] bit NOT NULL,
              [AccessFailedCount] int NOT NULL,
              CONSTRAINT [PK_AspNetUsers] PRIMARY KEY ([Id])
          );
    

    提示

    ef 命令是否引发了有关 LocalDb 不受支持的错误? 请确保已设置连接字符串,如“配置数据库连接”部分所述!

  4. 你接受建议的扩展后,SQL Server 扩展被添加到 Visual Studio Code(如果需要)。 按 Ctrl+Alt+ D 可切换到 SQL Server 窗格

  5. 展开现有数据库连接下的节点。 展开“数据库”节点、“RazorPagesPizza”节点,最后展开“表”节点。 记下表的列表。 这确认迁移成功。

    带有新创建的表的 RazorPagesPizza 数据库。

    注意

    上图显示了使用 SQL Server Express LocalDB 的示例。 使用“.devcontainer”时,该连接名为“mssql-container”。

导航回“资源管理器”窗格。 在 Pages/Shared/_Layout.cshtml 中,使用以下内容替换 @* Add the _LoginPartial partial view *@ 注释。

<partial name="_LoginPartial" />

前面的标记在使用默认布局的任何页面的标头内呈现 _LoginPartial 分部视图。 _LoginPartial 由标识基架添加。 如果用户未登录,则此分部视图会向用户显示“登录”和“注册”链接。

测试标识功能

这是添加默认标识实现所需的所有内容。 是时候开始测试了!

  1. 确保你已保存所有更改。

  2. 在终端窗格中,生成项目并运行应用:

    dotnet run
    
  3. 像以前一样导航到浏览器中的应用。

  4. 选择应用标头中的“注册”链接。 填写表单以创建新帐户。

    随即显示“注册确认”页。 由于应用尚未配置为发送确认电子邮件,因此此页上提供确认链接。

  5. 选择确认链接。 此时会显示确认消息。

  6. 选择应用的标头中的“登录”链接并登录。

    成功登录后:

    • 随即重定向到主页。
    • 应用标头显示“Hello [email address]!”和“注销”链接。
    • 创建名为 .AspNetCore.Identity.Application 的 Cookie。 标识使用基于 Cookie 的身份验证保存用户会话。
  7. 选择应用标头中的“注销”链接。

    成功注销后,将删除 .AspNetCore.Identity.Application Cookie 以终止用户会话。

  8. 在终端窗格中,按 Ctrl+C 来停止应用

总结

在本单元中,你已将默认标识实现添加到现有 Web 应用。 在下一单元中,你将了解如何扩展和自定义标识。