在 ASP.NET Core 專案中建構 Identity

作者:Rick Anderson

本文將說明如何遷移資料庫並完成 Identity 支架更新。

Blazor Identity 鷹架

ASP.NET Core Identity scaffolding 會將 ASP.NET Core Identity 新增至 Blazor Web App 和 Blazor Server 應用程式中。 支架將元件加入 IdentityRazor 應用程式後,你可以依照應用程式需求自訂元件。

雖然支架會產生必要的 C# 程式碼來支架 Identity 進入應用程式,但你必須透過 Entity Framework Core 資料庫遷移更新專案資料庫才能完成此過程。 本文說明了資料庫遷移的步驟。

執行 Identity 腳手架後,檢查變更內容。 使用 GitHub 或其他帶有還原變更功能的檔案變更系統。

使用 雙因素驗證 (2FA)、Identity及其他安全功能時,需要相關服務。 對 Identity 執行 Scaffold 時,不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。

Razor 頁面與 MVC Identity 樣板產生

ASP.NET Core 會提供 ASP.NET Core Identity 作為 Razor 類別庫 (RCL)。 包括 Identity 的應用程式可以套用 Scaffolder,以選擇性新增 Identity RCL 中包含的原始程式碼。 建議您產生原始程式碼,以便能夠修改程式碼並變更行為。 例如,您可以指示 Scaffolder 產生註冊使用的程式碼。 自訂 Identity 程式碼會覆寫 Identity RCL 所提供的預設實作。 若要取得 UI 的完整控制權,而不使用預設 RCL,請參閱建立完整 Identity UI 來源一節。

包含驗證的應用程式可以套用框架來新增 RCL Identity 套件。 你可以選擇 Identity 程式碼來產生。

雖然腳手架工具會產生大部分所需的程式碼,但您仍需要更新專案,才能完成整個流程。 本文說明完成 Identity 鷹架更新所需的步驟。 執行 Identity 腳手架後,檢查變更內容。 使用能顯示檔案差異並允許你退出變更的版本控制系統。

使用雙重驗證(2FA)時,需要服務、帳號確認與密碼恢復,以及其他安全功能。Identity 對 Identity 執行 Scaffold 時,不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。 例如,請參見 「設定電子郵件提供者 ,使應用程式能要求電子郵件確認。」

一般而言,使用個別帳戶建立的應用程式「不應該」建立新的資料內容。

在 Identity 專案中建立 Blazor 骨架

本節所述的鷹架程序適用於 Blazor Web Apps 與 Blazor Server 應用程式。

執行 Identity 樣板產生器:

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Blazor Identity,然後選擇 新增

  4. 新增 BlazorIdentity 對話框中:

    1. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別

    2. 選取資料庫提供者 (資料庫提供者),其預設值為 SQL Server。

    3. 選擇加號圖示(+),並新增使用者類別, 使用者類別

    4. 選取 ,然後新增

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 下列步驟說明如何建立和套用移轉至資料庫。

Visual Studio 連接服務用於新增Entity Framework Core遷移並更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 More action...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

客戶端 Blazor 應用程式 (獨立式 Blazor WebAssembly)

用戶端 Blazor 應用程式 (獨立 Blazor WebAssembly) 會使用自己的 Identity UI 方法,而且無法使用 ASP.NET Core Identity Scaffolding。

如需詳細資訊,請參閱 Blazor 安全性和 Identity 文章

在沒有現有授權的情況下,將 Identity 建置至 Razor 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

版面配置變更

你可以將登入部分_LoginPartial()加入版面檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

使用授權將 Identity 建置至 Razor 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

在沒有現有授權的情況下,將 Identity 建置至 MVC 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

選擇性:將登入部分 (_LoginPartial) 新增至 Views/Shared/_Layout.cshtml 檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

如以下標示的程式碼所示,加入MapRazorPagesProgram.cs檔案:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.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.AddControllersWithViews();

var app = builder.Build();

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

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

app.UseRouting();

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

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

使用授權將 Identity 建置至 MVC 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

建立完整的 Identity UI 原始碼

若要保有對 Identity UI 的完全控制權,請執行 Identity scaffolder,並選取 覆寫所有檔案

密碼設定

如果 PasswordOptions 在 中配置Startup.ConfigureServices,則在支架頁面Identity中,StringLengthAttribute 設定可能是該屬性所必需Password的。 及其InputModelPassword屬性位於以下檔案中:

  • 區域/Identity/頁數/帳戶/Register.cshtml.cs
  • 區域/Identity/頁數/帳號/ResetPassword.cshtml.cs

停用頁面

本節說明如何停用暫存器頁面,但您也可以用同樣的方法來停用任何頁面。

若要停用使用者註冊:

  1. 鷹架 Identity。 包含 Account.RegisterAccount.LoginAccount.RegisterConfirmation。 例如:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  2. 更新 Areas/Identity/Pages/Account/Register.cshtml.cs 檔案,讓使用者無法從此端註冊:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  3. 更新 Areas/Identity/Pages/Account/Register.cshtml 檔案,使其與前述變更一致:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  4. 請留言或移除 Areas/Identity/Pages/Account/Login.cshtml 檔案中的註冊連結:

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  5. 更新 Areas/Identity/Pages/Account/RegisterConfirmation 頁面。

    • .cshtml 檔案中移除程式碼和連結。

    • 將確認碼從實作中 PageModel 移除:

    [AllowAnonymous]
    public class RegisterConfirmationModel : PageModel
    {
         public IActionResult OnGet()
         {  
             return Page();
         }
    }
    

使用另一個應用程式來新增使用者

提供在 Web 應用程式外部新增使用者的機制。 新增使用者的選項包括:

  • 專用的管理網頁應用程式
  • 一個控制台應用程式

以下程式碼說明了新增使用者的一種方法:

  • 把使用者名單讀進記憶。
  • 為每位使用者產生一個強而獨特的密碼。
  • 將使用者 Identity 加入資料庫。
  • 通知使用者更改密碼。
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

下列程式碼概述新增使用者:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

針對生產案例,可以遵循類似的方法。

防止發佈靜態 Identity 資產

若要防止將靜態 Identity 資產發佈至 Web 根目錄,請參閱 ASP.NET Core 上的 Identity 簡介

ASP.NET Core 會提供 ASP.NET Core Identity 作為 Razor 類別庫 (RCL)。 包括 Identity 的應用程式可以套用 Scaffolder,以選擇性新增 Identity RCL 中包含的原始程式碼。 建議您產生原始程式碼,以便能夠修改程式碼並變更行為。 例如,您可以指示 Scaffolder 產生註冊使用的程式碼。 產生的程式碼優先於 Identity RCL 中的相同程式碼。 若要取得 UI 的完整控制權,而不使用預設 RCL,請參閱建立完整 Identity UI 來源一節。

包含驗證的應用程式可以套用框架來新增 RCL Identity 套件。 您可以選擇選取要產生的 Identity 程式碼。

雖然腳手架工具會產生大部分所需的程式碼,但您仍需要更新專案,才能完成整個流程。 本文件說明完成 Identity 腳手架更新所需的步驟。

建議您使用原始檔控制系統來顯示檔案差異,並可讓您退出變更。 在執行 Identity 框架之後檢查變更。

使用雙因素驗證帳戶確認和密碼復原,以及其他具有 Identity 的安全性功能時都需要服務。 對 Identity 執行 Scaffold 時,不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。 例如,請參閱要求電子郵件確認

一般而言,使用個別帳戶建立的應用程式「不應該」建立新的資料內容。

在沒有現有授權的情況下,將 Identity 建置至 Razor 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

版面配置變更

選擇性:將登入部分 (_LoginPartial) 新增至版面配置檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

使用授權將 Identity 建置至 Razor 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

在沒有現有授權的情況下,將 Identity 建置至 MVC 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

選擇性:將登入部分 (_LoginPartial) 新增至 Views/Shared/_Layout.cshtml 檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRPnoAuth2Auth</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/WebRPnoAuth2Auth.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRPnoAuth2Auth</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                    <partial name="_LoginPartial" />
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2021 - WebRPnoAuth2Auth - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

MapRazorPages 新增至 Program.cs,如下列醒目提示的程式碼所示:

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebMVCauth.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.AddControllersWithViews();

var app = builder.Build();

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

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

app.UseRouting();

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

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");
app.MapRazorPages();

app.Run();

使用授權將 Identity 建置至 MVC 專案

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

將 Identity 樣板化為具備授權功能的伺服器端 Blazor 應用程式

安裝 Microsoft。VisualStudio.Web.CodeGeneration.DesignNuGet 套件。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。


請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

移轉

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

樣式驗證端點

因為伺服器端 Blazor 應用程式使用 Razor Pages Identity 頁面,因此當訪客在頁面和元件之間 Identity 巡覽時,UI 的樣式會變更。 您有兩個選項可解決不一致樣式:

自訂 Identity 元件

ASP.NET Core Identity 的設計目的是在 HTTP 要求和回應通訊的內容中運作,這不是 Blazor 應用程式中的主要用戶端-伺服器通訊模型。 使用 ASP.NET Core Identity 進行使用者管理的 ASP.NET Core 應用程式,應使用 Razor Pages,而非 Razor 元件,來處理 Identity 相關的 UI,例如使用者註冊、登入、登出及其他使用者管理工作。

由於 SignInManager<TUser> 元件不支援 UserManager<TUser> 和 Razor,因此我們建議使用 Web API 透過伺服器端支援 Identity 的 ASP.NET Core 應用程式來管理來自 Razor 元件的 Identity 動作。 如需為 Blazor 應用程式建立 Web API 的指引,請參閱從 ASP.NET Core Blazor 應用程式呼叫 Web API

使用 Razor 元件來處理 Identity,而非使用 Razor 頁面的其中一種做法,是建立您自己的自訂 IdentityRazor 元件,但 Microsoft 不建議也不支援這種做法。 如需其他內容,請探索下列討論。 在以下討論中,問題留言中的程式碼範例,以及在非 Microsoft GitHub 存放庫中交叉連結的程式碼範例,均不受 Microsoft 支援,但可能對某些開發人員有所幫助:

如需尋求建置自訂 IdentityRazor 元件或搜尋協力廠商 Razor 元件時的其他協助,建議您使用下列資源:

使用搭配 Blazor 應用程式樣式的自訂版面配置

您可以修改 Identity 版面配置和樣式,以產生使用類似預設 Blazor 主題樣式的頁面。 該文件並未涵蓋此方法。

用戶端 Blazor 應用程式

用戶端 Blazor 應用程式會使用自己的 Identity UI 方法,而且無法使用 ASP.NET Core Identity 進行建構。 裝載 Blazor 解決方案的伺服器端 ASP.NET Core 應用程式可以遵循本文中的 Razor Pages/MVC 指引,並且設定的方式就像支援 Identity 的任何其他 ASP.NET Core 應用程式類型一樣。

Blazor 架構不包含 Razor UI 頁面的 Identity 元件版本。 Identity UI Razor 元件可以自訂建置或從不支援的協力廠商來源取得。

如需詳細資訊,請參閱 Blazor 安全性和 Identity 文章

建立完整的 Identity UI 原始碼

若要保有對 Identity UI 的完全控制權,請執行 Identity scaffolder,並選取 覆寫所有檔案

密碼設定

如果在 PasswordOptions 中設定了 Startup.ConfigureServices,則對於 Scaffold 產生的 [StringLength] 頁面中的 屬性,可能需要設定 Identity組態。 InputModel Password 屬性可在下列檔案中找到:

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

停用頁面

本節說明如何停用註冊頁面,但該方法可用來停用任何頁面。

若要停用使用者註冊:

  • 鷹架 Identity。 包含 Account.Register、Account.Login 和 Account.RegisterConfirmation。 例如:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • 更新 Areas/Identity/Pages/Account/Register.cshtml.cs,讓使用者無法從此端點註冊:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • 更新 Areas/Identity/Pages/Account/Register.cshtml 以與上述變更一致:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • 將註冊連結註解掉,或從 Areas/Identity/Pages/Account/Login.cshtml 中移除

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • 更新 Areas/Identity/Pages/Account/RegisterConfirmation 頁面。

    • 從 cshtml 檔案移除程式碼和連結。
    • PageModel 移除確認碼:
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

使用另一個應用程式來新增使用者

提供在 Web 應用程式外部新增使用者的機制。 新增使用者的選項包括:

  • 專用的管理員 Web 應用程式。
  • 主控台應用程式。

下列程式碼概述一種新增使用者的方法:

  • 使用者清單會讀取到記憶體中。
  • 系統會為每個使用者產生唯一強式密碼。
  • 使用者會新增至 Identity 資料庫。
  • 系統會通知使用者並被告知要變更密碼。
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

下列程式碼概述新增使用者:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

針對生產案例,可以遵循類似的方法。

防止發佈靜態 Identity 資產

若要防止將靜態 Identity 資產發佈至 Web 根目錄,請參閱 ASP.NET Core 上的 Identity 簡介

ASP.NET Core 會提供 ASP.NET Core Identity 作為 Razor 類別庫 (RCL)。 包括 Identity 的應用程式可以套用 Scaffolder,以選擇性新增 Identity RCL 中包含的原始程式碼。 建議您產生原始程式碼,以便能夠修改程式碼並變更行為。 例如,您可以指示 Scaffolder 產生註冊使用的程式碼。 產生的程式碼優先於 Identity RCL 中的相同程式碼。 若要取得 UI 的完整控制權,而不使用預設 RCL,請參閱建立完整 Identity UI 來源一節。

包含驗證的應用程式可以套用框架來新增 RCL Identity 套件。 您可以選擇選取要產生的 Identity 程式碼。

雖然腳手架工具會產生大部分所需的程式碼,但您仍需要更新專案,才能完成整個流程。 本文件說明完成 Identity 腳手架更新所需的步驟。

建議您使用原始檔控制系統來顯示檔案差異,並可讓您退出變更。 在執行 Identity 框架之後檢查變更。

使用雙因素驗證帳戶確認和密碼復原,以及其他具有 Identity 的安全性功能時都需要服務。 對 Identity 執行 Scaffold 時,不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。 例如,請參閱要求電子郵件確認

針對具有現有個別帳戶的專案搭配新的資料內容對 Identity 進行 Scaffolding 時,請開啟 Startup.ConfigureServices 並移除對下列項目的呼叫:

  • AddDbContext
  • AddDefaultIdentity

例如,AddDbContextAddDefaultIdentity 會在下列程式碼中加上批註:

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

上述程式碼會批註 Areas/Identity/IdentityHostingStartup.cs 中重複的程式碼

一般而言,使用個別帳戶建立的應用程式「不應該」建立新的資料內容。

將 Identity 建立到空白專案中

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

使用類似下列的程式碼更新 Startup 類別:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

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

        app.UseRouting();

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

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

建議使用 UseHsts,但並非必要。 如需詳細資訊,請參閱 HTTP 嚴格的傳輸安全性通訊協定

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

在沒有現有授權的情況下,將 Identity 建置至 Razor 專案

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

Identity 是在 Areas/Identity/IdentityHostingStartup.cs 中設定的。 如需詳細資訊,請參閱IHostingStartup

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

啟用驗證

使用類似下列的程式碼更新 Startup 類別:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
    }

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

建議使用 UseHsts,但並非必要。 如需詳細資訊,請參閱 HTTP 嚴格的傳輸安全性通訊協定

版面配置變更

選擇性:將登入部分 (_LoginPartial) 新增至版面配置檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

使用授權將 Identity 建置至 Razor 專案

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

某些 Identity 選項是在 Areas/Identity/IdentityHostingStartup.cs 中設定的。 如需詳細資訊,請參閱IHostingStartup

在沒有現有授權的情況下,將 Identity 建置至 MVC 專案

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

選擇性:將登入部分 (_LoginPartial) 新增至 Views/Shared/_Layout.cshtml 檔案:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebRP</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebRP</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            &copy; 2019 - WebRP - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

Pages/Shared/_LoginPartial.cshtml 檔案移至 Views/Shared/_LoginPartial.cshtml

Identity 是在 Areas/Identity/IdentityHostingStartup.cs 中設定的。 如需詳細資訊,請參閱IHostingStartup

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

使用類似下列的程式碼更新 Startup 類別:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

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

        app.UseRouting();

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

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

建議使用 UseHsts,但並非必要。 如需詳細資訊,請參閱 HTTP 嚴格的傳輸安全性通訊協定

使用授權將 Identity 建置至 MVC 專案

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

在沒有現有授權機制的情況下,將 Identity 加入伺服器端 Blazor 應用程式中

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定一個新的類別。Identity

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

Identity 是在 Areas/Identity/IdentityHostingStartup.cs 中設定的。 如需詳細資訊,請參閱IHostingStartup

移轉

產生的 Identity 資料庫程式碼需要 Entity Framework Core 遷移。 如果尚未建立並套用到資料庫的遷移 Identity ,請使用以下程序建立遷移並更新資料庫。

Visual Studio 連線服務可用來新增 EF Core 移轉及更新資料庫。

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Add migration

  3. 為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。

    等候資料庫內容載入 [DbContext 類別名稱] 欄位。 動作可能持續幾秒鐘。

  4. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

  5. 選擇 更多動作...) >更新資料庫

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  6. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

update database 指令 Up 執行 scaffolder 建立的遷移碼檔中未套用的方法遷移。 此時,指令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行Up此方法,建立Identity表格、限制與索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已建立但未套用到資料庫,你只需執行更新資料庫的指令:

  1. 方案總管 中,按兩下 連接的服務

  2. SQL Server Express LocalDB 區域的 Service Dependencies,選擇 更多動作...) >Update database

    [使用最新的移轉更新資料庫] 對話方塊隨即開啟。

    等候 DbContext 類別名稱 欄位更新,以及等候先前的遷移載入。 動作可能持續幾秒鐘。

  3. 選擇 完成 以完成更新。 操作結束後,選擇 關閉

您可以使用下列命令來確認 Identity 架構的應用程式。 命令的輸出包含一個「applied」資料行,用來顯示哪些移轉已套用至資料庫。

在 Visual Studio 封裝管理員 控制台,執行 Get-Migration 指令:

Get-Migration

如果有多個資料庫內容存在,請使用 -Context 參數指定內容。

樣式驗證端點

因為伺服器端 Blazor 應用程式使用 Razor Pages Identity 頁面,因此當訪客在頁面和元件之間 Identity 巡覽時,UI 的樣式會變更。 您有兩個選項可解決不一致樣式:

自訂 Identity 元件

使用 Identity 元件 (而非頁面) 的一種方法是建置 Identity 元件。 因為 SignInManager 元件不支援 UserManager 和 Razor ,因此請使用 Blazor 應用程式中的 Web API 端點來處理使用者帳戶動作。

使用搭配 Blazor 應用程式樣式的自訂版面配置

您可以修改 Identity 版面配置和樣式,以產生使用類似預設 Blazor 主題樣式的頁面。 該文件並未涵蓋此方法。

將 Identity 樣板化為具備授權功能的伺服器端 Blazor 應用程式

請依照以下程序運行 Identity 鷹架。

  1. 方案總管,右鍵點擊專案,選擇 Add>New Scaffolded Item

  2. 「新增鷹架項目 」對話框的左側窗格中,選擇 Identity

  3. 在中間窗格,選擇 Identity,然後選擇 新增

  4. 新增 Identity 對話框中,選擇你想要的選項:

    1. 如果你已有自訂版面頁面(_Layout.cshtml),Identity請選擇現有頁面,以避免支架錯誤的標記覆蓋版面。 例如,選擇以下其中之一:

      • Pages/Shared/_Layout.cshtml 用於Razor已有 Razor Pages 基礎設施的頁面或Blazor Server專案。
      • 用於 MVC 專案或Blazor Server已有 MVC 基礎架構的專案的 Views/Shared/_Layout.cshtml
    2. 選擇加號圖示(+)並新增資料庫上下文類別 DbContext 類別。 您必須選取至少一個檔案來新增您的資料內容。

      • 要建立資料上下文,請選擇加號圖示(+)。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。

      • 要建立新的使用者類別,請選擇使用者類別的加號圖示(+)並指定類別(例如ContosoUser,某家名為「Contoso」的公司)。

    3. 選擇 新增 以執行鷹架架。

某些 Identity 選項是在 Areas/Identity/IdentityHostingStartup.cs 中設定的。 如需詳細資訊,請參閱IHostingStartup

用戶端 Blazor 應用程式

用戶端 Blazor 應用程式會使用自己的 Identity UI 方法,而且無法使用 ASP.NET Core Identity 進行建構。 裝載 Blazor 解決方案的伺服器端 ASP.NET Core 應用程式可以遵循本文中的 Razor Pages/MVC 指引,並且設定的方式就像支援 Identity 的任何其他 ASP.NET Core 應用程式類型一樣。

Blazor 架構不包含 Razor UI 頁面的 Identity 元件版本。 Identity UI Razor 元件可以自訂建置或從不支援的協力廠商來源取得。

如需詳細資訊,請參閱 Blazor 安全性和 Identity 文章

建立完整的 Identity UI 原始碼

若要保有對 Identity UI 的完全控制權,請執行 Identity scaffolder,並選取 覆寫所有檔案

以下醒目提示的程式碼顯示在 ASP.NET Core 2.1 Web 應用程式中以 Identity 取代預設 Identity UI 的變更。 您可能想要執行此動作,以完全控制 Identity UI。

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.AddIdentity<IdentityUser, IdentityRole>()
        // services.AddDefaultIdentity<IdentityUser>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc()
        .AddRazorPagesOptions(options =>
        {
            options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
            options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
        });

    services.ConfigureApplicationCookie(options =>
    {
        options.LoginPath = $"/Identity/Account/Login";
        options.LogoutPath = $"/Identity/Account/Logout";
        options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
    });

    // using Microsoft.AspNetCore.Identity.UI.Services;
    services.AddSingleton<IEmailSender, EmailSender>();
}

預設的 Identity 會在下列程式碼中被取代:

services.AddIdentity<IdentityUser, IdentityRole>()
    // services.AddDefaultIdentity<IdentityUser>()
    .AddEntityFrameworkStores<ApplicationDbContext>()
    .AddDefaultTokenProviders();

下列程式碼會設定 LoginPathLogoutPathAccessDeniedPath):

services.ConfigureApplicationCookie(options =>
{
    options.LoginPath = $"/Identity/Account/Login";
    options.LogoutPath = $"/Identity/Account/Logout";
    options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});

註冊 IEmailSender 實作,例如:

// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
public class EmailSender : IEmailSender
{
    public Task SendEmailAsync(string email, string subject, string message)
    {
        return Task.CompletedTask;
    }
}

密碼設定

如果在 PasswordOptions 中設定了 Startup.ConfigureServices,則對於 Scaffold 產生的 [StringLength] 頁面中的 屬性,可能需要設定 Identity組態。 InputModel Password 屬性可在下列檔案中找到:

  • Areas/Identity/Pages/Account/Register.cshtml.cs
  • Areas/Identity/Pages/Account/ResetPassword.cshtml.cs

停用頁面

本節說明如何停用註冊頁面,但該方法可用來停用任何頁面。

若要停用使用者註冊:

  • 鷹架 Identity。 包含 Account.Register、Account.Login 和 Account.RegisterConfirmation。 例如:

    dotnet aspnet-codegenerator identity -dc RPauth.Data.ApplicationDbContext --files "Account.Register;Account.Login;Account.RegisterConfirmation"
    
  • 更新 Areas/Identity/Pages/Account/Register.cshtml.cs,讓使用者無法從此端點註冊:

    public class RegisterModel : PageModel
    {
        public IActionResult OnGet()
        {
            return RedirectToPage("Login");
        }
    
        public IActionResult OnPost()
        {
            return RedirectToPage("Login");
        }
    }
    
  • 更新 Areas/Identity/Pages/Account/Register.cshtml 以與上述變更一致:

    @page
    @model RegisterModel
    @{
        ViewData["Title"] = "Go to Login";
    }
    
    <h1>@ViewData["Title"]</h1>
    
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
    
  • 將註冊連結註解掉,或從 Areas/Identity/Pages/Account/Login.cshtml 中移除

    @*
    <p>
        <a asp-page="./Register" asp-route-returnUrl="@Model.ReturnUrl">Register as a new user</a>
    </p>
    *@
    
  • 更新 Areas/Identity/Pages/Account/RegisterConfirmation 頁面。

    • 從 cshtml 檔案移除程式碼和連結。
    • PageModel 移除確認碼:
    [AllowAnonymous]
      public class RegisterConfirmationModel : PageModel
      {
          public IActionResult OnGet()
          {  
              return Page();
          }
      }
    

使用另一個應用程式來新增使用者

提供在 Web 應用程式外部新增使用者的機制。 新增使用者的選項包括:

  • 專用的管理員 Web 應用程式。
  • 主控台應用程式。

下列程式碼概述一種新增使用者的方法:

  • 使用者清單會讀取到記憶體中。
  • 系統會為每個使用者產生唯一強式密碼。
  • 使用者會新增至 Identity 資料庫。
  • 系統會通知使用者並被告知要變更密碼。
public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;

            try
            {
                var context = services.GetRequiredService<AppDbCntx>();
                context.Database.Migrate();

                var config = host.Services.GetRequiredService<IConfiguration>();
                var userList = config.GetSection("userList").Get<List<string>>();

                SeedData.Initialize(services, userList).Wait();
            }
            catch (Exception ex)
            {
                var logger = services.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred adding users.");
            }
        }

        host.Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

下列程式碼概述新增使用者:


public static async Task Initialize(IServiceProvider serviceProvider,
                                    List<string> userList)
{
    var userManager = serviceProvider.GetService<UserManager<IdentityUser>>();

    foreach (var userName in userList)
    {
        var userPassword = GenerateSecurePassword();
        var userId = await EnsureUser(userManager, userName, userPassword);

        NotifyUser(userName, userPassword);
    }
}

private static async Task<string> EnsureUser(UserManager<IdentityUser> userManager,
                                             string userName, string userPassword)
{
    var user = await userManager.FindByNameAsync(userName);

    if (user == null)
    {
        user = new IdentityUser(userName)
        {
            EmailConfirmed = true
        };
        await userManager.CreateAsync(user, userPassword);
    }

    return user.Id;
}

針對生產案例,可以遵循類似的方法。

防止發佈靜態 Identity 資產

若要防止將靜態 Identity 資產發佈至 Web 根目錄,請參閱 ASP.NET Core 上的 Identity 簡介

其他資源

將驗證碼變更為 ASP.NET Core 2.1 或更新版本