一、前言
在前面的篇章介紹中,一些基礎配置如API資源、客戶端資源等資料以及使用程序中發放的令牌等操作資料,我們都是通過將操作資料和配置資料存盤在記憶體中進行實作的,而在實際開發生產中,我們需要考慮如何處理資料持久化呢?
這時IdentityServer4具有良好的擴展性,其中一個可擴展點是用于IdentityServer所需資料的存盤機制,進行持久化操作,
下面將如何配置IdentityServer以使用EntityFramework(EF)作為此資料的存盤機制把這些資料存盤到Sql Server資料庫, 這樣更符合我們實際生產環境的需求,
二、初識
在我們的 IdentityServer4中官方定義的兩個背景關系,是有兩種型別的資料需要持久化到資料庫中:
1、配置資料(資源、客戶端、身份);//這里是對應配置背景關系
ConfigurationDbContext2、IdentityServer在使用時產生的 操作資料(令牌,代碼和用戶的授權資訊consents);//這里是對應操作背景關系
PersistedGrantDbContext
這兩個背景關系以及對應的資料模型,已經被 IdentityServer4 官方給封裝好了, 我們不需要欄位外的操作,直接進行遷移即可使用,
2.1 ConfigurationDb
ConfigurationDbContext (IdentityServer configuration data) —— 負責資料庫中對客戶端、資源和 CORS 設定的配置存盤;
如果需要從 EF 支持的資料庫加載客戶端、標識資源、API 資源或 CORS 資料 (而不是使用記憶體中配置), 則可以使用配置存盤,此支持提供 IClientStore、IResura Store 和 ICorsPolicyService 擴展性點的實作,這些實作使用名為 ConfigurationDbContext 的 dbcontext 派生類對資料庫中的表進行建模,
2.2 PersistedGrantDb
PersistedGrantDbContext (IdentityServer operational data.) -—— 負責存盤同意、授權代碼、重繪令牌和參考令牌;
如果需要從 EF 支持的資料庫 (而不是默認的記憶體資料庫) 加載授權授予、同意和令牌 (重繪和參考), 則可以使用操作存盤,此支持提供了 IPersistedGrantStore 擴展點的實作,實作使用名為 PersistedGrantDbContext 的 dbcontext 派生類對資料庫中的表進行建模,
三、實踐
3.1 新建站點
建立一個MVC的Asp.Net Core專案 ,使用MVC模板
3.2 Nuget包
IdentityServer4.EntityFramework以及EF相關包
1.IdentityServer4
2.IdentityServer4.AspNetIdentity
3.IdentityServer4.EntityFramework
因為本文中使用的是SqlServer資料庫,所以需要安裝對應的EF程式包對資料庫的支持,
Microsoft.EntityFrameworkCore.SqlServer
3.3 資料庫背景關系
appsettings.json
"ConnectionStrings": {
"DataContext": "data source=.;initial catalog=Yuan.Idp;user id=sa;password=123456;",
}
配置連接資料庫
var connectionString = Configuration.GetConnectionString("DataContext");
if (connectionString == "")
{
throw new Exception("資料庫配置例外");
}
2.配置資料庫服務
在startup.cs中ConfigureServices方法添加如下代碼:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var connectionString = Configuration.GetConnectionString("DataContext");
if (connectionString == "")
{
throw new Exception("資料庫配置例外");
}
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// in DB config
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
}).AddConfigurationStore(options => //添加配置資料(ConfigurationDbContext背景關系用戶配置資料)
{
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
}).AddOperationalStore(options => //添加操作資料(PersistedGrantDbContext背景關系 臨時資料(如授權和重繪令牌))
{
options.ConfigureDbContext = builder => builder.UseSqlServer(connectionString, sql => sql.MigrationsAssembly(migrationsAssembly));
// 自動清理 token ,可選
options.EnableTokenCleanup = true;
// 自動清理 token ,可選
options.TokenCleanupInterval = 30;
}).AddTestUsers(TestUsers.Users);
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
services.ConfigureNonBreakingSameSiteCookies();
}
3.4 遷移資料
3.4.1 控制臺遷移
方法一:
需要添加EF工具,安裝Microsoft.EntityFrameworkCore.Tools, 進行遷移
1、add-migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/PersistedGrantDb
2、add-migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/ConfigurationDb
3、update-database -Context PersistedGrantDbContext
4、update-database -Context ConfigurationDbContext

3.4.2 在命令視窗
方法二:
判斷是否支持命令列遷移,你可以在專案所在的目錄下打開一個命令 Power shell 并運行命令 dotnet ef, 它應該是這樣的:

dotnet ef 無法執行,因為找不到指定的命令或檔案
從 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另裝,命令如下:
dotnet tool install --global dotnet-ef
要創建遷移,請在IdentityServer專案目錄中打開命令提示符, 在命令提示符下運行這兩個命令:
1. dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/PersistedGrantDb
2. dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/ConfigurationDb
#生成
1. update-database -c PersistedGrantDbContext
2. update-database -c ConfigurationDbContext

3.5 顯示資料庫


(圖片來自網路)
3.6 初始化資料庫
在之前的篇章中,我們是定義的記憶體配置資料實作的操作,而在本篇中,我們進行資料持久化操作,可以將之前記憶體的資料作為種子處理遷移到創建的資料庫中進行初始化操作,
參考文章: 用戶資料遷移
3.6.1 創建檔案
創建SeedData.cs檔案,用于初始化基礎資料:
public class SeedData
{
public static void EnsureSeedData(IServiceProvider serviceProvider)
{
Console.WriteLine("Seeding database...");
using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
scope.ServiceProvider.GetService<PersistedGrantDbContext>().Database.Migrate();
var context = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
context.Database.Migrate();
EnsureSeedData(context);
}
Console.WriteLine("Done seeding database.");
Console.WriteLine();
}
private static void EnsureSeedData(ConfigurationDbContext context)
{
if (!context.Clients.Any())
{
Console.WriteLine("Clients 正在初始化");
foreach (var client in Config.GetClients)
{
context.Clients.Add(client.ToEntity());
}
context.SaveChanges();
}
if (!context.IdentityResources.Any())
{
Console.WriteLine("IdentityResources 正在初始化");
foreach (var resource in Config.GetIdentityResources)
{
context.IdentityResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiResources.Any())
{
Console.WriteLine("ApiResources 正在初始化");
foreach (var resource in Config.GetApiResources)
{
context.ApiResources.Add(resource.ToEntity());
}
context.SaveChanges();
}
if (!context.ApiScopes.Any())
{
Console.WriteLine("ApiScopes 正在初始化");
foreach (var resource in Config.GetApiScopes)
{
context.ApiScopes.Add(resource.ToEntity());
}
context.SaveChanges();
}
}
}
配置內容可以查看之前篇章內容檔案Config.cs 或者專案地址.
3.6.2 呼叫方法
然后我們可以從主入口Main方法呼叫它:
public static void Main(string[] args)
{
var seed = args.Contains("/seed");
if (seed)
{
args = args.Except(new[] { "/seed" }).ToArray();
}
var host = CreateHostBuilder(args).Build();
if (seed)
{
SeedData.EnsureSeedData(host.Services);
}
host.Run();
}
3.6.3 程式運行
輸入 dotnet run /seed

3.6.4 效果

四、問題
4.1 提示找不到背景關系
上面我們說到了的兩個背景關系,如果我們直接通過執行遷移命令是會報錯的,比如我們直接遷移 PersistedGrantDbContext 背景關系:

因為遷移的目標不匹配,需要更改遷移程式集,如
options.UseSqlServer(connection, b => b.MigrationsAssembly("Ids4.EFCore"))
所以,就需要在專案中配置對應的服務,我們在 startup.cs 啟動檔案中,配置服務 ConfigureService ,配置 EF 操作資料庫.
解決方法 : 可參考上面的實踐部分中的資料庫背景關系.
獲取資料庫連接字串
配置資料庫服務
4.2 dotnet ef 無法執行
因為找不到指定的命令或檔案
從 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另裝,命令如下:
dotnet tool install --global dotnet-ef
五、總結
- 簡單介紹了IdentityServer4持久化存盤機制相關配置和操作資料,實作了資料遷移,及應用程式的實踐,
- 本篇未對用戶進行持久化操作存盤說明,因為IdentityServer4本就支持了接入其他認證方式,所以自己根據需要進行合理擴展的,比如我們可以使用 Asp.Net Core 自帶的 Identity 身份認證機制來實作擴展,當然,你也可以自己定義相應的操作,在后續篇章中會進行說明介紹,
- 如果有不對的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學習,共同進步,
- 專案地址
六、附加
EF支持持久化配置和操作資料
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/241166.html
標籤:.NET Core
上一篇:設計模式 - 18)單例模式
