ASP.NET Core プロジェクトでの Identity のスキャフォールディング

作成者: Rick Anderson

ASP.NET Core では、ASP.NET Core IdentityRazor クラス ライブラリとして提供しています。 Identity を含むアプリケーションで、IdentityRazor クラス ライブラリ (RCL) に含まれるソース コードを選択的に追加するようにスキャフォールディングを適用できます。 コードを変更して動作を変更できるように、ソース コードを生成できます。 たとえば、登録で使用するコードを生成するようにスキャフォルダーに指示できます。 生成されたコードは、Identity RCL の同じコードよりも優先されます。 UI を完全に制御し、既定の RCL を使用しないようにするには、「完全な Identity UI ソースを作成する」セクションを参照してください。

認証を含まないアプリケーションでは、RCL Identity パッケージを追加するようにスキャフォールディングを適用できます。 生成される Identity コードの選択オプションがあります。

スキャフォールディングによって、必要なコードの大部分が生成されますが、プロセスを完了するにはプロジェクトを更新する必要があります。 このドキュメントでは、Identity スキャフォールディングの更新を完了するために必要な手順について説明します。

ファイルの差分が表示され、変更を取り消すことができるソース管理システムを使用することをお勧めします。 Identity スキャフォールディングを実行した後、変更内容を検査します。

サービスは、Identity で 2 要素認証アカウントの確認とパスワードの回復、およびその他のセキュリティ機能を使用する場合に必要です。 サービスまたはサービス スタブは、Identity のスキャフォールディング時に生成されません。 これらの機能を有効にするサービスは、手動で追加する必要があります。 たとえば、電子メール確認の要求に関する記事をご覧ください。

通常は、個別のアカウントで作成されたアプリで、新しいデータ コンテキストを作成 "しない" ようにする必要があります。

Razor プロジェクトに既存の認可なしで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

移行、UseAuthentication、レイアウト

生成された Identity データベース コードには、Entity Framework Core 移行が必要です。 Identity スキーマを作成するための移行が作成されておらず、データベースに適用されていない場合は、移行を作成してデータベースを更新します。 たとえば、次のコマンドを実行します。

Visual Studio パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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>

Razor プロジェクトに認可ありで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

MVC プロジェクトに既存の認可なしで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

省略可能: ログイン部分 (_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 パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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();

MVC プロジェクトに認可ありで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

クライアントサイド Blazor アプリ

クライアント側の Blazor アプリでは独自の Identity UI アプローチを使用し、ASP.NET Core Identity スキャフォールディングを使用することはできません。

サーバー側の ASP.NET Core アプリは、この記事の Razor Pages/MVC ガイダンスに従うことができ、Identity をサポートする他の種類の ASP.NET Core アプリと同様に構成します。 Blazor フレームワークでは、Identity を Blazor Web アプリにスキャフォールディングするときに Identity UI ページ (.cshtml) の Razor コンポーネント バージョン (.razor) を使用します。

詳細については、Blazor セキュリティと Identity に関する記事をご覧ください。

完全な Identity UI ソースを作成する

Identity UI の完全な制御を維持するには、Identity スキャフォールディングを実行し、[すべてのファイルをオーバーライド] を選択します。

パスワードの構成

PasswordOptionsStartup.ConfigureServices で構成されている場合、[StringLength] 属性の構成が、スキャフォールディングされる Identity ページの Password プロパティに必要になることがあります。 InputModelPassword プロパティは、次のファイルにあります。

  • 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 アプリ。
  • コンソール アプリ。

次のコードは、ユーザーを追加する 1 つの方法の概要を示しています。

  • ユーザーの一覧がメモリに読み込まれる。
  • ユーザーごとに強力な一意のパスワードが生成される。
  • ユーザーが 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 IdentityRazor クラス ライブラリとして提供しています。 Identity を含むアプリケーションで、IdentityRazor クラス ライブラリ (RCL) に含まれるソース コードを選択的に追加するようにスキャフォールディングを適用できます。 コードを変更して動作を変更できるように、ソース コードを生成できます。 たとえば、登録で使用するコードを生成するようにスキャフォルダーに指示できます。 生成されたコードは、Identity RCL の同じコードよりも優先されます。 UI を完全に制御し、既定の RCL を使用しないようにするには、「完全な Identity UI ソースを作成する」セクションを参照してください。

認証を含まないアプリケーションでは、RCL Identity パッケージを追加するようにスキャフォールディングを適用できます。 生成される Identity コードの選択オプションがあります。

スキャフォールディングによって、必要なコードの大部分が生成されますが、プロセスを完了するにはプロジェクトを更新する必要があります。 このドキュメントでは、Identity スキャフォールディングの更新を完了するために必要な手順について説明します。

ファイルの差分が表示され、変更を取り消すことができるソース管理システムを使用することをお勧めします。 Identity スキャフォールディングを実行した後、変更内容を検査します。

サービスは、Identity で 2 要素認証アカウントの確認とパスワードの回復、およびその他のセキュリティ機能を使用する場合に必要です。 サービスまたはサービス スタブは、Identity のスキャフォールディング時に生成されません。 これらの機能を有効にするサービスは、手動で追加する必要があります。 たとえば、電子メール確認の要求に関する記事をご覧ください。

通常は、個別のアカウントで作成されたアプリで、新しいデータ コンテキストを作成 "しない" ようにする必要があります。

Razor プロジェクトに既存の認可なしで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

移行、UseAuthentication、レイアウト

生成された Identity データベース コードには、Entity Framework Core 移行が必要です。 Identity スキーマを作成するための移行が作成されておらず、データベースに適用されていない場合は、移行を作成してデータベースを更新します。 たとえば、次のコマンドを実行します。

Visual Studio パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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>

Razor プロジェクトに認可ありで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

MVC プロジェクトに既存の認可なしで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

省略可能: ログイン部分 (_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 パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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();

MVC プロジェクトに認可ありで Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

承認を使用してサーバーサイド Blazor アプリに Identity をスキャフォールディングする

次の Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet パッケージをインストールします。

Note

.NET アプリへのパッケージの追加に関するガイダンスについては、「パッケージ利用のワークフロー」 (NuGet ドキュメント) の "パッケージのインストールと管理" に関する記事を参照してください。 NuGet.org で正しいパッケージ バージョンを確認します。


Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

移行

生成された Identity データベース コードには、Entity Framework Core 移行が必要です。 Identity スキーマを作成するための移行が作成されておらず、データベースに適用されていない場合は、移行を作成してデータベースを更新します。 たとえば、次のコマンドを実行します。

Visual Studio パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 Identity スキーマのアプリケーションを確認できます。 コマンドの出力には、データベースに適用される移行を示す "applied" 列が含まれています。

Visual Studio パッケージ マネージャー コンソールの場合は、Get-Migration を実行します:

Get-Migration

複数のデータベース コンテキストが存在する場合は、-Context パラメーターを使用してコンテキストを指定します。

認証エンドポイントをスタイル設定する

サーバーサイド Blazor アプリでは RazorPagesIdentity ページが使用されているため、訪問者が Identity ページとコンポーネント間を移動すると、UI のスタイルが変わります。 調和していないスタイルに対処するには、次の 2 つの選択肢があります。

カスタム Identity コンポーネント

ASP.NET Core Identity は、要求と応答の HTTP 通信のコンテキストで動作するように設計されています。これは、Blazor アプリの主要なクライアント/サーバー通信モデルではありません。 ユーザー管理に ASP.NET Core Identity を使用する ASP.NET Core アプリでは、ユーザー登録、ログイン、ログアウト、その他のユーザー管理タスクなど、Identity 関連の UI 用に、Razor コンポーネントではなく Razor Pages を使用する必要があります。

SignInManager<TUser>UserManager<TUser> は Razor コンポーネントではサポートされていないため、Web API を使って、サーバー側 Identity 対応 ASP.NET Core アプリを介して Razor コンポーネントから Identity アクションを管理することをお勧めします。 Blazor アプリ用の Web API を作成するためのガイダンスについては、ASP.NET Core Blazor アプリから Web API を呼び出す方法に関する記事を参照してください。

Razor Pages の代わりに Identity に対して Razor コンポーネントを使用する方法の 1 つは、独自のカスタム 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 コンポーネント バージョンの Identity UI ページは含まれていません。 Identity UI Razor コンポーネントは、カスタムで作成するか、サポートされていないサードパーティのソースから取得できます。

詳細については、Blazor セキュリティと Identity に関する記事をご覧ください。

完全な Identity UI ソースを作成する

Identity UI の完全な制御を維持するには、Identity スキャフォールディングを実行し、[すべてのファイルをオーバーライド] を選択します。

パスワードの構成

PasswordOptionsStartup.ConfigureServices で構成されている場合、[StringLength] 属性の構成が、スキャフォールディングされる Identity ページの Password プロパティに必要になることがあります。 InputModelPassword プロパティは、次のファイルにあります。

  • 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 アプリ。
  • コンソール アプリ。

次のコードは、ユーザーを追加する 1 つの方法の概要を示しています。

  • ユーザーの一覧がメモリに読み込まれる。
  • ユーザーごとに強力な一意のパスワードが生成される。
  • ユーザーが 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 IdentityRazor クラス ライブラリとして提供しています。 Identity を含むアプリケーションで、IdentityRazor クラス ライブラリ (RCL) に含まれるソース コードを選択的に追加するようにスキャフォールディングを適用できます。 コードを変更して動作を変更できるように、ソース コードを生成できます。 たとえば、登録で使用するコードを生成するようにスキャフォルダーに指示できます。 生成されたコードは、Identity RCL の同じコードよりも優先されます。 UI を完全に制御し、既定の RCL を使用しないようにするには、「完全な Identity UI ソースを作成する」セクションを参照してください。

認証を含まないアプリケーションでは、RCL Identity パッケージを追加するようにスキャフォールディングを適用できます。 生成される Identity コードの選択オプションがあります。

スキャフォールディングによって、必要なコードの大部分が生成されますが、プロセスを完了するにはプロジェクトを更新する必要があります。 このドキュメントでは、Identity スキャフォールディングの更新を完了するために必要な手順について説明します。

ファイルの差分が表示され、変更を取り消すことができるソース管理システムを使用することをお勧めします。 Identity スキャフォールディングを実行した後、変更内容を検査します。

サービスは、Identity で 2 要素認証アカウントの確認とパスワードの回復、およびその他のセキュリティ機能を使用する場合に必要です。 サービスまたはサービス スタブは、Identity のスキャフォールディング時に生成されません。 これらの機能を有効にするサービスは、手動で追加する必要があります。 たとえば、電子メール確認の要求に関する記事をご覧ください。

既存の個別のアカウントで、新しいデータ コンテキストを持つプロジェクトに Identity をスキャフォールディングする場合は、次のようにします。

  • 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 スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

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 パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 Identity スキーマのアプリケーションを確認できます。 コマンドの出力には、データベースに適用される移行を示す "applied" 列が含まれています。

Visual Studio パッケージ マネージャー コンソールの場合は、Get-Migration を実行します:

Get-Migration

複数のデータベース コンテキストが存在する場合は、-Context パラメーターを使用してコンテキストを指定します。

Razor プロジェクトに既存の認可なしで Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

Identity は Areas/Identity/IdentityHostingStartup.cs で構成されます。 詳細については、IHostingStartup に関する記事をご覧ください。

移行、UseAuthentication、レイアウト

生成された Identity データベース コードには、Entity Framework Core 移行が必要です。 Identity スキーマを作成するための移行が作成されておらず、データベースに適用されていない場合は、移行を作成してデータベースを更新します。 たとえば、次のコマンドを実行します。

Visual Studio パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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>

Razor プロジェクトに認可ありで Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

一部の Identity オプションは、Areas/Identity/IdentityHostingStartup.cs 内で構成されます。 詳細については、IHostingStartup に関する記事をご覧ください。

MVC プロジェクトに既存の認可なしで Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

省略可能: ログイン部分 (_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 パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 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 トランスポート セキュリティのプロトコルに関するページを参照してください。

MVC プロジェクトに認可ありで Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

既存の承認なしでサーバーサイド Blazor アプリに Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

Identity は Areas/Identity/IdentityHostingStartup.cs で構成されます。 詳細については、IHostingStartupを参照してください。

移行

生成された Identity データベース コードには、Entity Framework Core 移行が必要です。 Identity スキーマを作成するための移行が作成されておらず、データベースに適用されていない場合は、移行を作成してデータベースを更新します。 たとえば、次のコマンドを実行します。

Visual Studio パッケージ マネージャー コンソールの場合:

Install-Package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore
Add-Migration CreateIdentitySchema
Update-Database

Add-Migration コマンドの "CreateIdentitySchema" name パラメーターは任意です。 "CreateIdentitySchema" は移行について説明するものです。

Identity スキーマが既に作成されているが、データベースに適用されていない場合は、データベースを更新するコマンドのみを実行する必要があります:

Visual Studio パッケージ マネージャー コンソールの場合は、Update-Database を実行します:

Update-Database

次のコマンドを使用して、 Identity スキーマのアプリケーションを確認できます。 コマンドの出力には、データベースに適用される移行を示す "applied" 列が含まれています。

Visual Studio パッケージ マネージャー コンソールの場合は、Get-Migration を実行します:

Get-Migration

複数のデータベース コンテキストが存在する場合は、-Context パラメーターを使用してコンテキストを指定します。

認証エンドポイントをスタイル設定する

サーバーサイド Blazor アプリでは RazorPagesIdentity ページが使用されているため、訪問者が Identity ページとコンポーネント間を移動すると、UI のスタイルが変わります。 調和していないスタイルに対処するには、次の 2 つの選択肢があります。

カスタム Identity コンポーネント

ページの代わりに Identity のコンポーネントを使用する方法で、Identity コンポーネントを構築します。 SignInManagerUserManager は Razor コンポーネントでサポートされていないため、Blazor アプリで web API エンドポイントを使用してユーザー アカウントの操作を処理します。

Blazor アプリのスタイルでカスタム レイアウトを使用する

Identity ページのレイアウトとスタイルを変更して、既定の Blazor テーマと似たようなスタイルを使用するページを生成できます。 この方法については、ドキュメントでは説明しません。

承認を使用してサーバーサイド Blazor アプリに Identity をスキャフォールディングする

Identity スキャフォールディングを実行します。

  • [ソリューション エクスプローラー] で、プロジェクトを右クリックし、>[追加]>[新しいスキャフォールディング アイテム] の順に選択します。
  • [新規スキャフォールディング アイテムの追加] の左ペインから [Identity] を選択します。 中央のウィンドウで [Identity] を選択します。 追加 ボタンを選択します。
  • [Identity の追加] ダイアログで、必要なオプションを選択します。
    • Identity (_Layout.cshtml) 用にカスタマイズされた既存のレイアウト ページがある場合は、既存のレイアウト ページを選択して、スキャフォールディングによって正しくないマークアップでレイアウトが上書きされないようにします。 たとえば、次のいずれかを選択します:
      • 既存の Razor Pages インフラストラクチャが含まれる、Razor Pages プロジェクトまたは Blazor Server プロジェクトの Pages/Shared/_Layout.cshtml
      • 既存の MVC インフラストラクチャが含まれる、MVC プロジェクトまたは Blazor Server プロジェクトの Views/Shared/_Layout.cshtml
    • データ コンテキスト (DbContext クラス) の場合:
      • データ コンテキスト クラスを選択します。 データ コンテキストを追加するには、1 つ以上のファイルを選択する必要があります。
      • データ コンテキストを作成し、Identity の新しいユーザー クラスを作成するには、+ ボタンを選択します。 既定値をそのまま使用するか、クラスを指定します (たとえば、 "Contoso" という名前の会社の場合は Contoso.Data.ApplicationDbContext)。 新しいユーザー クラスを作成するには、[+ユーザー クラス] のボタンを選択し、クラスを指定します (たとえば、ContosoUser"Contoso" という名前の会社の場合)。
    • [追加] ボタンを選択してスキャフォールディングを実行します。

一部の 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 コンポーネント バージョンの Identity UI ページは含まれていません。 Identity UI Razor コンポーネントは、カスタムで作成するか、サポートされていないサードパーティのソースから取得できます。

詳細については、Blazor セキュリティと Identity に関する記事をご覧ください。

完全な Identity UI ソースを作成する

Identity UI の完全な制御を維持するには、Identity スキャフォールディングを実行し、[すべてのファイルをオーバーライド] を選択します。

次の強調表示されたコードは、ASP.NET Core 2.1 Web アプリで既定の Identity UI を Identity に置き換える変更を示しています。 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;
    }
}

パスワードの構成

PasswordOptionsStartup.ConfigureServices で構成されている場合、[StringLength] 属性の構成が、スキャフォールディングされる Identity ページの Password プロパティに必要になることがあります。 InputModelPassword プロパティは、次のファイルにあります。

  • 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 アプリ。
  • コンソール アプリ。

次のコードは、ユーザーを追加する 1 つの方法の概要を示しています。

  • ユーザーの一覧がメモリに読み込まれる。
  • ユーザーごとに強力な一意のパスワードが生成される。
  • ユーザーが 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 の概要」を参照してください。

その他のリソース