構成データと運用データにEntityFramework Coreを使用する

IdentityServerは拡張性のために設計されており、拡張性のポイントの1つは、IdentityServerが必要とするデータに使用される記憶メカニズムです。このクイックスタートでは、EntityFramework(EF)をこのデータのストレージメカニズムとして使用するようにIdentityServerを設定する方法を示します(今まで使用していたインメモリ実装を使用するのではなく)。

注釈

EFサポートを手動で設定するだけでなく、EFサポートで新しいプロジェクトを作成するためのIdentityServerテンプレートもあります。それを作成するために使用します。詳細はこちらを参照してください。dotnet new is4ef

IdentityServer4.EntityFramework

データベースに移動するデータには2種類あります。1つは設定データ(リソースとクライアント)です。2つ目はIdentityServerが使用中に生成する操作データ(トークン、コード、同意)です。これらのストアはインタフェースでモデル化されており、これらのインタフェースのEF実装をIdentityServer4.EntityFramework Nugetパッケージに提供しています。

まず、IdentityServerプロジェクトのIdentityServer4.EntityFramework Nugetパッケージへの参照を追加します。

../_images/8_nuget.png

SqlServerの使用

EFの柔軟性を考えると、EFでサポートされているデータベースを使用できます。このクイックスタートでは、Visual Studioに付属するLocalDbバージョンのSqlServerを使用します。

データベーススキーマの変更とEF移行の使用

IdentityServer4.EntityFrameworkのパッケージには、IdentityServerのモデルからマップするエンティティクラスが含まれています。IdentityServerのモデルが変更されると、IdentityServer4.EntityFrameworkのエンティティクラスも変更されます。IdentityServer4.EntityFrameworkを使用して時間をかけてアップグレードするときには、独自のデータベーススキーマと、エンティティクラスの変更に応じてそのスキーマに必要な変更を行う責任があります。これらの変更を管理するための1つのアプローチは、EF移行を使用することです。このクイックスタートでは、その方法を示します。移行があなたの好みでない場合は、スキーマの変更を適切な方法で管理できます。

注釈

SqlServer用のSQLスクリプトは、IdentityServer4.EntityFrameworkのエンティティ用にメンテナンスされています。彼らはここに位置しています。

移行のためのEFツーリング

EF移行を使用してスキーマの変更を追跡することに加えて、これを使用してデータベースに初期スキーマを作成します。これには、EFコアツールの使用が必要です(詳細はこちら)。これらを今追加します。残念ながら、これは.csprojファイルを手動で編集する必要があります。プロジェクトを右クリックし、 "edit projectname.csproj"を選択して.csprojを編集するには:

注釈

IdentityServerホストの初期プロジェクトの作成方法に応じて、csprojファイルでこれらのツールを設定している可能性があります。そうであれば、次のセクションに進むことができます。

../_images/8_edit_csproj.png

そして、最後の</ Project>要素の前にスニペットを追加します。

<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.0" />
</ItemGroup>

これは次のようになります。

../_images/8_csproj.png

ファイルを保存して閉じます。ツールが正しくインストールされていることをテストするには、プロジェクトと同じディレクトリにコマンドシェルを開き、dotnet efを実行します。これは次のようになります。

../_images/8_dotnet_ef_command_line.png

Configuring the stores

次のステップは、現在の通話交換することでAddInMemoryClients、AddInMemoryIdentityResources、そしてAddInMemoryApiResources内ConfigureServicesでの方法Startup.csを。このコードで置き換えます:

const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.Quickstart.EntityFramework-2.0.0;trusted_connection=yes;";
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddTestUsers(Config.GetUsers())
    // this adds the config data from DB (clients, resources)
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    // this adds the operational data from DB (codes, tokens, consents)
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = builder =>
            builder.UseSqlServer(connectionString,
                sql => sql.MigrationsAssembly(migrationsAssembly));

        // this enables automatic token cleanup. this is optional.
        options.EnableTokenCleanup = true;
        options.TokenCleanupInterval = 30;
    });

これらの名前空間をファイルに追加する必要があるかもしれません:

using Microsoft.EntityFrameworkCore;
using System.Reflection;

上記のコードは、接続文字列をハードコーディングしています。必要に応じて変更することができます。また、への呼び出しAddConfigurationStoreとは、AddOperationalStoreEF-裏打ちされた店舗の実装を登録しています。

これらのAPIに渡される「ビルダー」コールバック関数は、これらの2つのストアのそれぞれDbContextOptionsBuilderに対してfor を構成できるEFメカニズムですDbContext。これはDbContext、使用するデータベースプロバイダを使用してクラスを構成する方法です。この場合、UseSqlServer私たちはSqlServerを使用して呼び出します。また、これは接続文字列が提供される場所です。

in "options"コールバック関数UseSqlServerは、EF移行が定義されているアセンブリを構成するものです。EFでは、データベースのスキーマを定義するためにマイグレーションを使用する必要があります。

注釈

これらの移行は、データベースとプロバイダに固有のものであるため、ホスティング・アプリケーションでこれらの移行を定義する必要があります。

次に移行を追加します。

移行の追加

移行を作成するには、IdentityServerプロジェクトディレクトリでコマンドプロンプトを開きます。コマンドプロンプトで、次の2つのコマンドを実行します。

dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb

これは次のようになります。

../_images/8_add_migrations.png

あなたは今見るべきである〜/データ/移行/ IdentityServerのプロジェクトにフォルダを。これには、新しく作成された移行のコードが含まれています。

注釈

データベースプロジェクトが別のクラスライブラリで、 '<your-name> DbContext'型のオブジェクトを作成できませんでした。'IDesignTimeDbContextFactory'の実装をプロジェクトに追加するか、デザイン時にサポートされている追加のパターンについてはhttps://go.microsoft.com/fwlink/?linkid=851728を参照してください。IDesignTimeDbContextFactoryの実装を追加することによって、PersistedGrantDbContextとConfigurationDbContextの両方のファクトリの実装が必要になります。

データベースの初期化

これで移行が完了したため、移行からデータベースを作成するコードを記述できます。また、前のクイックスタートで定義したメモリ内の構成データをデータベースにシードします。

でStartup.csデータベースを初期化するために、このメソッドを追加します。

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

        var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
        context.Database.Migrate();
        if (!context.Clients.Any())
        {
            foreach (var client in Config.GetClients())
            {
                context.Clients.Add(client.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            foreach (var resource in Config.GetIdentityResources())
            {
                context.IdentityResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.ApiResources.Any())
        {
            foreach (var resource in Config.GetApiResources())
            {
                context.ApiResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }
    }
}

そして、Configureメソッドから呼び出すことができます:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    // this will do the initial DB population
    InitializeDatabase(app);

    // the rest of the code that was already here
    // ...
}

IdentityServerプロジェクトを実行する場合は、データベースを作成し、クイックスタート構成データをシードします。SQL Server Management StudioまたはVisual Studioを使用して、データの接続および検査を行うことができます。

../_images/8_database.png

注釈

上記のInitializeDatabaseヘルパーAPIは、データベースをシードするのに便利ですが、このアプローチは、アプリケーションが実行されるたびに実行するのが理想的ではありません。データベースが移入されたら、APIへの呼び出しを削除することを検討してください。

クライアントアプリケーションを実行する

これで、データベース構成に基づいて、既存のクライアントアプリケーションを実行してサインインし、トークンを取得し、APIを呼び出すことができるようになりました。

注釈

このセクションにあるコードは、Config.csとその架空のユーザーAliceとBobに依然として依存しています。ユーザーリストが短く静的な場合は、調整されたConfig.csのバージョンで十分ですが、データベース内でより大きくて流動的なユーザーリストを動的に管理したい場合があります。ASP.NET IDは考慮すべきオプションの1つで、このソリューションのサンプル実装は次のセクションのクイックスタートに一覧表示されています。