演習 - Identity のサポートを構成する

完了

Identity は、カスタマイズしなくてもすぐに使用できます。 このユニットでは、Identity を既存の ASP.NET Core Razor Pages プロジェクトに追加します。

スターター プロジェクトを取得して開く

Note

GitHub Codespaces で .devcontainer を使う場合は、MicrosoftDocs/mslearn-secure-aspnet-core-identity リポジトリのお使いの codespace に移動します。 main ブランチを使用して新しい codespace を作成し、手順 3 に進みます。

  1. ターミナル ウィンドウで、次のコマンドを実行してスターター プロジェクトを取得します。

    git clone https://github.com/MicrosoftDocs/mslearn-secure-aspnet-core-identity
    
  2. ソース コード ディレクトリに切り替えて、Visual Studio Code を起動します。

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

    Visual Studio Code が開きます。 推奨される拡張機能のインストールを求めるプロンプトを受け入れるか、.devcontainerを使用する場合は、[コンテナーで再度開く] を選択します。

    ヒント

    コンテナーで再度開くためのプロンプトが表示されない場合は、Ctrl+Shift+P キーを押してコマンド パレットを開き、「Dev Containers: コンテナーで再度開く」を検索して選びます。

  3. プロジェクトが (ローカルで、またはコンテナー内に) 読み込まれたら、Ctrl+Shift+` キーを押して新しいターミナル ウィンドウを開きます。

  4. 新しいターミナル ウィンドウで、場所を RazorPagesPizza ディレクトリに設定します。

    cd RazorPagesPizza
    
  5. エクスプローラー ウィンドウで、RazorPagesPizza ディレクトリを展開してコードを表示します。 RazorPagesPizza はプロジェクト ディレクトリです。 これ以降、このモジュールで説明するすべてのパスは、この場所を基準にするものとします。

アプリを探索する

では、アプリを実行して概要を理解することにしましょう。

  1. ターミナル ウィンドウで、プロジェクトをビルドし、アプリを実行します。

    dotnet run
    
  2. ターミナル出力に表示される URL をメモしてください。 たとえば、「 https://localhost:7192 」のように入力します。

  3. Ctrl キーを押しながら "クリック"して、その URL を選択し、ブラウザーでアプリを開きます。

    重要

    Docker で .devcontainer を使用している場合、コンテナー内からの SSL 証明書は、ブラウザーによって信頼されません。 Web アプリを表示するには、次のいずれかの操作を行う必要があります。

    • 証明書エラーを無視します。 Microsoft Edge を使用している場合は、[詳細設定][localhost へ移動 (非推奨)] を選択します。 詳細はブラウザーによって異なります。
    • 証明書を保存し、信頼できる証明機関に追加します。
    • コンテナー内に既存の開発証明書をインポートします。 詳細については、./devcontainer/devcontainter.json に生成されるコメントを参照してください。

    コンテナー内に既存の開発証明書をインポートすることを選択する場合、コンテナー パス /root/.aspnet/ は、コンテナーの外部で .devcontainer/persisted-data/.aspnet として公開されます。 これは便宜上です。

    GitHub Codespaces で .devcontainer を使用している場合、アクションは必要ありません。 codespace では、プロキシ SSL 接続が自動的に処理されます。

  4. ブラウザーで Web アプリを探索します。 ヘッダーのリンクを使用して、次の操作を行います。

    1. [ピザ リスト]に移動する
    2. [ホーム] に戻る

    認証が要求されないことに注目してください。

  5. ターミナル ウィンドウで、Ctrl+C キーを押してアプリを停止します。

ASP.NET Core ID をプロジェクトに追加する

既定の ID 実装は、dotnet コマンドライン ツールを使用して追加できます。

  1. ASP.NET Core コード スキャフォールディングをインストールします。

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

    スキャフォールディングは、次のような .NET Core ツールです。

    • プロジェクトに既定の Identity コンポーネントを追加するために使われます。
    • 次のユニットで Identity UI コンポーネントをカスタマイズできるようにします。
    • このモジュールでは dotnet aspnet-codegenerator を介して呼び出されます。
  2. 次の NuGet パッケージをプロジェクトに追加します。

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

    これらのパッケージによって、スキャフォールディングで使用されるコード生成テンプレートと依存関係がインストールされます。

    ヒント

    使用可能なジェネレーターを表示するには:

    • コマンド シェルで dotnet aspnet-codegenerator -h を実行します。
    • Visual Studio を使用しているときは、ソリューション エクスプローラーでプロジェクトを右クリックし、[追加]>[新規スキャフォールディング アイテム] を選択します。
  3. スキャフォールディングを使用して、プロジェクトに既定の Identity コンポーネントを追加します。 ターミナルで次のコマンドを実行します。

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

    上記のコマンドでは次のことが行われます。

    • プロジェクトへの Identity フレームワークの追加には、identity として識別されるジェネレーターが使用されます。
    • --useDefaultUI オプションで、既定の UI 要素を含む Razor クラス ライブラリ (RCL) を使うことを指示します。 コンポーネントのスタイルを設定するには、Bootstrap が使われます。
    • --dbContext オプションは、生成する EF Core データ コンテキスト クラスの名前を指定します。

    次の Areas ディレクトリ構造が RazorPagesPizza ディレクトリに表示されます。

    • Areas
      • Identity (Areas と同じ行に表示されます)
        • Data
          • RazorPagesPizzaAuth.cs
        • Pages
          • _ValidationScriptsPartial.cshtml
          • _ViewStart.cshtml

    ヒント

    Areas ディレクトリがエクスプローラー ウィンドウに自動的に表示されない場合は、エクスプローラー ウィンドウの MSLEARN-SECURE-ASPNET-CORE-IDENTITY ヘッダーの [エクスプローラーを最新表示する] を選択します。

    Areas では、ASP.NET Core Web アプリをより小さい機能グループに分割する手段が提供されます。

    また、スキャフォールディングによって、以下の強調表示した変更が Program.cs に加えられ、読みやすいように再フォーマットされました。

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

    上のコードでは以下の操作が行われます。

    • RazorPagesPizzaAuthConnection 接続文字列は、appsettings.json から読み取られます。
    • RazorPagesPizzaAuthという名前の EF Core データ コンテキスト クラスは、接続文字列を使用して構成されます。
    • Identity サービスが登録されます。これには、既定の UI、トークン プロバイダー、および Cookie ベースの認証が含まれます。
      • .AddDefaultIdentity<IdentityUser> は、ID サービスに対して、既定のユーザー モデルを使用するように指示します。
      • ラムダ式 options => options.SignIn.RequireConfirmedAccount = true は、ユーザーが自分のメール アカウントを確認する必要があることを指定します。
      • .AddEntityFrameworkStores<RazorPagesPizzaAuth>() は、ID で、データベースに既定の Entity Framework Core ストアを使用することを指定します。 RazorPagesPizzaAuthDbContextクラスが使用されます。
    • app.UseAuthentication(); により、認証機能が有効になります。 具体的には、ASP.NET Core 認証ミドルウェアのインスタンスが、アプリの HTTP 要求処理パイプラインに追加されます。

データベース接続を構成する

appsettings.json 内の ConnectionStrings セクションは、次の JSON のようになります。

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

この接続文字列は、既定で SQL Server Express LocalDB のインスタンスを指します。 .devcontainer を使っている場合は、接続文字列を次のように変更する必要があります。 変更を保存します。

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

これにより、接続文字列が更新され、コンテナー内の SQL Server のインスタンスに接続されるようになります。

データベースを更新する

接続文字列を確認したので、移行を生成して実行し、データベースを構築することができます。

  1. 次のコマンドを実行して、アプリをビルドします。

    dotnet build
    

    ビルドは警告なしで成功します。 ビルドに失敗した場合は、出力でトラブルシューティング情報を確認してください。

  2. Entity Framework Core 移行ツールをインストールします。

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

    移行ツールは、次のような .NET ツールです。

    • Identity エンティティ モデルをサポートするデータベースを作成および更新するための、移行と呼ばれるコードを生成します。
    • 既存のデータベースに対して移行を実行します。
    • このモジュールでは dotnet ef を介して呼び出されます。
  3. EF Core の移行を作成して実行し、データベースを更新します。

    dotnet ef migrations add CreateIdentitySchema
    dotnet ef database update
    

    CreateIdentitySchema EF Core の移行では、データ定義言語 (DDL) の変更スクリプトを適用して、Identity をサポートするテーブルを作成しました。 たとえば、次の出力は、移行によって生成される CREATE TABLE ステートメントを示しています。

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

    ヒント

    ef コマンドは、LocalDb がサポートされていないことに関するエラーをスローしましたか? 「データベース接続を構成する」セクションの説明に従って接続文字列を設定したことを確認します。

  4. SQL Server 拡張機能は、推奨される拡張機能を受け入れたときに、必要に応じて Visual Studio Code に追加されています。 Ctrl+Alt+D キーを押して、SQL Server ウィンドウに切り替えます。

  5. 既存のデータベース接続の下にあるノードを展開します。 Databases ノード、RazorPagesPizza ノードの順に展開し、最後に Tables ノードを展開します。 テーブルの一覧に注目してください。 これにより、移行が成功したことを確認できます。

    新しく作成されたテーブルがある RazorPagesPizza データベース。

    Note

    上の画像は、SQL Server Express LocalDB の使用例を示しています。 .devcontainer を使用している場合、接続は mssql-container という名前です。

[エクスプローラー] ペインに戻ります。 Pages/Shared/_Layout.cshtml で、コメント @* Add the _LoginPartial partial view *@ を以下に置き換えます。

<partial name="_LoginPartial" />

上記のマークアップでは、既定のレイアウトを使用するすべてのページのヘッダー内に _LoginPartial 部分ビューがレンダリングされます。 _LoginPartial は、Identity スキャフォールディングによって追加されています。 この部分ビューでは、ユーザーがサインインしていない場合に、[ログイン] および [登録] リンクがユーザーに表示されます。

ID 機能をテストする

既定の ID 実装を追加する場合、必要なのはこれだけです。 では、テストを始めましょう。

  1. すべての変更を保存したことを確認します。

  2. ターミナル ウィンドウで、プロジェクトをビルドし、アプリを実行します。

    dotnet run
    
  3. 前と同じように、ブラウザーでアプリに移動します。

  4. アプリのヘッダーの [登録] (Register) リンクを選びます。 フォームに入力して、新しいアカウントを作成します。

    [登録の確認] ページが表示されます。 アプリはまだ、確認メールを送信するように構成されていないため、このページに確認リンクが表示されます。

  5. 確認リンクを選びます。 確認メッセージが表示されます。

  6. アプリのヘッダーで [ログイン] (Login) リンクを選んでサインインします。

    正常にサインインした後:

    • ホーム ページにリダイレクトされます。
    • アプリのヘッダーに、[Hello <メール アドレス>!] (こんにちは <メール アドレス>!)[Logout] (ログアウト) リンクが表示されます。
    • .AspNetCore.Identity.Application という名前の Cookie が作成されます。 Identity では、Cookie ベースの認証を使用してユーザー セッションが保持されます。
  7. アプリのヘッダーで [Logout] (ログアウト) リンクを選びます。

    ログアウトが正常に完了すると、.AspNetCore.Identity.Application Cookie が削除されてユーザー セッションが終了されます。

  8. ターミナル ウィンドウで、Ctrl+C キーを押してアプリを停止します。

まとめ

このユニットでは、既定の ID 実装を既存の Web アプリに追加しました。 次のユニットでは、ID の拡張とカスタマイズについて学習します。