共用方式為


在 ASP.NET Core 專案中建構 Identity

作者:Rick Anderson

BlazorIdentity Scaffolding

ASP.NET Core Identity Scaffolding 會將 ASP.NET Core Identity 新增至 Blazor Web Apps 和 Blazor Server 應用程式。 Scaffolder 將 IdentityRazor 元件新增至應用程式之後,您可以自訂元件以符合您應用程式的需求。

雖然 Scaffolder 會產生必要的 C# 程式碼來針對應用程式對 Identity 進行 Scaffold,但您必須使用 Entity Framework (EF) Core 資料庫移轉來更新專案的資料庫,以完成此流程。 本文說明移轉資料庫所需的步驟。

在執行 Identity 框架之後檢查變更。 我們建議使用 GitHub 或其他原始檔控制系統,其能顯示檔案變更,並具有還原變更功能。

使用雙因素驗證 (2FA)帳戶確認和密碼復原 (部分機器翻譯),以及其他具有 Identity 的安全性功能時都需要服務。 在產生 Identity 時不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。

Razor Pages 和 MVC Identity Scaffolding

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 框架之後檢查變更。

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

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

針對 Blazor 專案對 Identity 進行 Scaffold

本節適用於 Blazor Web Apps 和 Blazor Server 應用程式。

執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Blazor Identity。 選取新增按鈕。
  • 在 [新增 BlazorIdentity] 對話方塊中:
    • 選取或新增具有加號 (+) 按鈕的資料庫內容類別 (DbContext 類別)。
    • 選取資料庫提供者 (資料庫提供者),其預設值為 SQL Server。
    • 選取或新增具有加號 (+) 按鈕的使用者類別 (User 類別)。
    • 選取新增按鈕。

產生的 Identity 資料庫程式碼需要 EF Core 移轉 (部分機器翻譯)。 下列步驟說明如何建立和套用移轉至資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 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.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

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

安裝 Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

選擇性:將登入部分 (_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 (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

建立完整的 Identity UI 來源

若要維護 UI 的完整控制權 Identity ,請執行 Identity 建構並選取 [ 覆寫所有檔案 ]。

密碼設定

如果在 Startup.ConfigureServices 中設定 PasswordOptions[StringLength] 屬性組態可能需要已建構 Identity 頁面中的 Password 屬性。 InputModel Password 屬性可在下列檔案中找到:

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

停用頁面

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

若要停用使用者註冊:

  • Scaffold 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 時不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。 例如,請參閱要求電子郵件確認

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

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

安裝 Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

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

安裝 Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

選擇性:將登入部分 (_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 (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

使用授權將 Identity 建置至伺服器端 Blazor 應用程式

安裝 Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet 套件。

注意

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


執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

移轉

產生的 Identity 資料庫程式碼需要 Entity Framework (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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,例如使用者註冊、登入、登出和其他使用者管理工作。

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

使用 Razor 元件取代 Razor 頁面進行 Identity 的方法,是建立自己的自訂 Identity Razor 元件,但 Microsoft 不建議或不支援這種方法。 如需其他內容,請探索下列討論。 在下列討論中,Microsoft 不支援在非 Microsoft GitHub 存放庫中交叉連結的問題批註和程式碼範例中的程式碼範例,但對某些開發人員可能很有説明:

如需尋求建置自訂 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 架構不包含 Identity UI 頁面的 Razor 元件版本。 Identity UI Razor 元件可以自訂建置或從不支援的協力廠商來源取得。

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

建立完整的 Identity UI 來源

若要維護 UI 的完整控制權 Identity ,請執行 Identity 建構並選取 [ 覆寫所有檔案 ]。

密碼設定

如果在 Startup.ConfigureServices 中設定 PasswordOptions[StringLength] 屬性組態可能需要已建構 Identity 頁面中的 Password 屬性。 InputModel Password 屬性可在下列檔案中找到:

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

停用頁面

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

若要停用使用者註冊:

  • Scaffold 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 時不會產生服務或服務存根。 啟用這些功能的服務必須手動新增。 例如,請參閱要求電子郵件確認

針對具有現有個別帳戶的專案搭配新的資料內容對 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 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

使用類似下列的程式碼更新 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 (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

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

在 Visual Studio 套件管理員主控台中,執行 Get-Migration

Get-Migration

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

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

執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

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

移轉、UseAuthentication 和配置

產生的 Identity 資料庫程式碼需要 Entity Framework (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

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

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

執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

選擇性:將登入部分 (_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 (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

您可以使用下列命令來確認 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 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

在沒有現有授權的情況下,將 Identity 建構入伺服器端 Blazor 應用程式

執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

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

移轉

產生的 Identity 資料庫程式碼需要 Entity Framework (EF) Core 移轉 (部分機器翻譯)。 如果尚未建立產生 Identity 結構描述的移轉並套用至資料庫,請建立移轉並更新資料庫。

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

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [新增移轉]

為移轉提供 [移轉名稱],例如 CreateIdentitySchema,其為描述移轉的名稱。 等候資料庫內容載入 [DbContext 類別名稱] 欄位,這可能需要幾秒鐘的時間。 選取 [完成] 以建立移轉。

在作業完成之後,選取 [關閉] 按鈕。

再次選取省略符號 (...),接著選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

更新資料庫命令會執行尚未在 Scaffolder 所建立的移轉程式碼檔案中套用的 Up 方法移轉。 在此情況下,命令會在 Migrations/{TIME STAMP}_{MIGRATION NAME}.cs 檔案中執行 Up 方法,其會建立 Identity 資料表、條件約束和索引。 {TIME STAMP} 預留位置是時間戳記,而 {MIGRATION NAME} 預留位置是移轉名稱。

如果 Identity 架構已經建立,但未套用至資料庫,則必須執行更新資料庫的命令:

在 [方案總管] 中,按兩下 [已連線的服務]。 在 [服務相依性] 的 [SQL Server Express LocalDB] 區域中,選取省略符號 (...),然後選取 [更新資料庫] 命令。

[使用最新的移轉更新資料庫] 對話方塊隨即開啟。 等候 [DbContext 類別名稱] 欄位更新,以及等候先前的移轉載入,這可能需要幾秒鐘的時間。 選取 [完成] 按鈕。

在作業完成之後,選取 [關閉] 按鈕。

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

在 Visual Studio 套件管理員主控台中,執行 Get-Migration

Get-Migration

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

樣式驗證端點

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

自訂 Identity 元件

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

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

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

使用授權將 Identity 建置至伺服器端 Blazor 應用程式

執行 Identity 框架:

  • 從 [方案總管] 中,以滑鼠右鍵按一下專案 >[新增]>[新增 Scaffold 項目]
  • 從 [新增 Scaffold 項目] 對話方塊的左窗格中,選取 Identity。 在中央窗格中選取 Identity。 選取新增按鈕。
  • 在 [新增 Identity] 對話方塊中,選取您想要的選項。
    • 如果您有 Identity (_Layout.cshtml) 的現有自訂版面配置頁面,請選取現有的版面配置頁面,以避免覆寫框架不正確的標記覆寫您的版面配置。 例如,選取下列其中一項:
      • 具有現有 Razor Pages 基礎結構的 Razor Pages 或 Blazor Server 專案的 Pages/Shared/_Layout.cshtml
      • MVC 專案的 Views/Shared/_Layout.cshtml 或具有現有 MVC 基礎設施的 Blazor Server 專案。
    • 針對資料內容 (DbCoNtext 類別):
      • 選取您的資料內容類別。 您必須選取至少一個檔案來新增您的資料內容。
      • 若要建立資料內容,並可能為 Identity 建立新的使用者類別,請選取 + 按鈕。 接受預設值或指定類別 (例如,適用於名為「Contoso」公司的 Contoso.Data.ApplicationDbContext)。 若要建立新的使用者類別,請選取 User 類別+按鈕,然後指定類別 (例如,適用於名為「Contoso」公司的 ContosoUser)。
    • 選取 [新增] 按鈕以執行框架。

某些 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 架構不包含 Identity UI 頁面的 Razor 元件版本。 Identity UI Razor 元件可以自訂建置或從不支援的協力廠商來源取得。

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

建立完整的 Identity UI 來源

若要維護 UI 的完整控制權 Identity ,請執行 Identity 建構並選取 [ 覆寫所有檔案 ]。

以下醒目提示的程式碼顯示在 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;
    }
}

密碼設定

如果在 Startup.ConfigureServices 中設定 PasswordOptions[StringLength] 屬性組態可能需要已建構 Identity 頁面中的 Password 屬性。 InputModel Password 屬性可在下列檔案中找到:

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

停用頁面

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

若要停用使用者註冊:

  • Scaffold 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 和更新版本