IdentityServer4系列 | 支持数据持久化
一、前言
在前面的篇章介紹中,一些基礎(chǔ)配置如API資源、客戶端資源等數(shù)據(jù)以及使用過程中發(fā)放的令牌等操作數(shù)據(jù),我們都是通過將操作數(shù)據(jù)和配置數(shù)據(jù)存儲(chǔ)在內(nèi)存中進(jìn)行實(shí)現(xiàn)的,而在實(shí)際開發(fā)生產(chǎn)中,我們需要考慮如何處理數(shù)據(jù)持久化呢?
這時(shí)「IdentityServer4」具有良好的擴(kuò)展性,其中一個(gè)可擴(kuò)展點(diǎn)是用于「IdentityServer」所需數(shù)據(jù)的存儲(chǔ)機(jī)制,進(jìn)行持久化操作。
下面將如何配置「IdentityServer」以使用「EntityFramework」(EF)作為此數(shù)據(jù)的存儲(chǔ)機(jī)制把這些數(shù)據(jù)存儲(chǔ)到「Sql Server」數(shù)據(jù)庫(kù), 這樣更符合我們實(shí)際生產(chǎn)環(huán)境的需求。
二、初識(shí)
在我們的 「IdentityServer4」中官方定義的兩個(gè)上下文,是有兩種類型的數(shù)據(jù)需要持久化到數(shù)據(jù)庫(kù)中:
?1、「配置數(shù)據(jù)」(資源、客戶端、身份);//這里是對(duì)應(yīng)配置上下文 「ConfigurationDbContext」
2、「IdentityServer」在使用時(shí)產(chǎn)生的 「操作數(shù)據(jù)」(令牌,代碼和用戶的授權(quán)信息consents);//這里是對(duì)應(yīng)操作上下文 「PersistedGrantDbContext」
?「這兩個(gè)上下文以及對(duì)應(yīng)的數(shù)據(jù)模型,已經(jīng)被 IdentityServer4 官方給封裝好了」, 我們不需要做額外的操作,直接進(jìn)行遷移即可使用。
2.1 ConfigurationDb
ConfigurationDbContext (IdentityServer configuration data) —— 負(fù)責(zé)數(shù)據(jù)庫(kù)中對(duì)客戶端、資源和 CORS 設(shè)置的配置存儲(chǔ);
如果需要從 EF 支持的數(shù)據(jù)庫(kù)加載客戶端、標(biāo)識(shí)資源、API 資源或 CORS 數(shù)據(jù) (而不是使用內(nèi)存中配置), 則可以使用配置存儲(chǔ)。此支持提供 IClientStore、IResura Store 和 ICorsPolicyService 擴(kuò)展性點(diǎn)的實(shí)現(xiàn)。這些實(shí)現(xiàn)使用名為 ConfigurationDbContext 的 「dbcontext」 派生類對(duì)數(shù)據(jù)庫(kù)中的表進(jìn)行建模。
2.2 PersistedGrantDb
PersistedGrantDbContext (IdentityServer operational data.) -—— 負(fù)責(zé)存儲(chǔ)同意、授權(quán)代碼、刷新令牌和引用令牌;
如果需要從 EF 支持的數(shù)據(jù)庫(kù) (而不是默認(rèn)的內(nèi)存數(shù)據(jù)庫(kù)) 加載授權(quán)授予、同意和令牌 (刷新和引用), 則可以使用操作存儲(chǔ)。此支持提供了 IPersistedGrantStore 擴(kuò)展點(diǎn)的實(shí)現(xiàn)。實(shí)現(xiàn)使用名為 PersistedGrantDbContext 的 「dbcontext」 派生類對(duì)數(shù)據(jù)庫(kù)中的表進(jìn)行建模。
三、實(shí)踐
3.1 新建站點(diǎn)
建立一個(gè)MVC的Asp.Net Core項(xiàng)目 ,使用MVC模板
3.2 Nuget包
IdentityServer4.EntityFramework以及EF相關(guān)包
1.IdentityServer4 2.IdentityServer4.AspNetIdentity 3.IdentityServer4.EntityFramework因?yàn)楸疚闹惺褂玫氖荢qlServer數(shù)據(jù)庫(kù),所以需要安裝對(duì)應(yīng)的EF程序包對(duì)數(shù)據(jù)庫(kù)的支持。
Microsoft.EntityFrameworkCore.SqlServer3.3 數(shù)據(jù)庫(kù)上下文
appsettings.json
??"ConnectionStrings":?{"DataContext":?"data?source=.;initial?catalog=Yuan.Idp;user?id=sa;password=123456;",???}配置連接數(shù)據(jù)庫(kù)
?var?connectionString?=?Configuration.GetConnectionString("DataContext");if?(connectionString?==?""){throw?new?Exception("數(shù)據(jù)庫(kù)配置異常");}2.配置數(shù)據(jù)庫(kù)服務(wù)
在startup.cs中ConfigureServices方法添加如下代碼:
????????public?void?ConfigureServices(IServiceCollection?services){services.AddControllersWithViews();var?connectionString?=?Configuration.GetConnectionString("DataContext");if?(connectionString?==?""){throw?new?Exception("數(shù)據(jù)庫(kù)配置異常");}var?migrationsAssembly?=?typeof(Startup).GetTypeInfo().Assembly.GetName().Name;//?in?DB??configvar?builder?=?services.AddIdentityServer(options?=>{options.Events.RaiseErrorEvents?=?true;options.Events.RaiseInformationEvents?=?true;options.Events.RaiseFailureEvents?=?true;options.Events.RaiseSuccessEvents?=?true;}).AddConfigurationStore(options?=>?//添加配置數(shù)據(jù)(ConfigurationDbContext上下文用戶配置數(shù)據(jù)){options.ConfigureDbContext?=?builder?=>?builder.UseSqlServer(connectionString,?sql?=>?sql.MigrationsAssembly(migrationsAssembly));}).AddOperationalStore(options?=>???//添加操作數(shù)據(jù)(PersistedGrantDbContext上下文?臨時(shí)數(shù)據(jù)(如授權(quán)和刷新令牌)){options.ConfigureDbContext?=?builder?=>?builder.UseSqlServer(connectionString,?sql?=>?sql.MigrationsAssembly(migrationsAssembly));//?自動(dòng)清理?token?,可選options.EnableTokenCleanup?=?true;//?自動(dòng)清理?token?,可選options.TokenCleanupInterval?=?30;}).AddTestUsers(TestUsers.Users);//?not?recommended?for?production?-?you?need?to?store?your?key?material?somewhere?securebuilder.AddDeveloperSigningCredential();services.ConfigureNonBreakingSameSiteCookies();}3.4 遷移數(shù)據(jù)
3.4.1 控制臺(tái)遷移
方法一:
需要添加EF工具,安裝Microsoft.EntityFrameworkCore.Tools, 進(jìn)行遷移
??1、add-migration?InitialIdentityServerPersistedGrantDbMigration?-c?PersistedGrantDbContext?-o?Data/Migrations/PersistedGrantDb?2、add-migration?InitialIdentityServerConfigurationDbMigration?-c?ConfigurationDbContext?-o?Data/Migrations/ConfigurationDb?3、update-database?-Context?PersistedGrantDbContext4、update-database?-Context?ConfigurationDbContext???3.4.2 在命令窗口
方法二:
判斷是否支持命令行遷移,你可以在項(xiàng)目所在的目錄下打開一個(gè)命令 Power shell 并運(yùn)行命令 dotnet ef, 它應(yīng)該是這樣的:
?dotnet ef 無法執(zhí)行,因?yàn)檎也坏街付ǖ拿罨蛭募?/p>
從 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另裝。命令如下:
dotnet?tool?install?--global?dotnet-ef ?要?jiǎng)?chuàng)建遷移,請(qǐng)?jiān)贗dentityServer項(xiàng)目目錄中打開命令提示符。在命令提示符下運(yùn)行這兩個(gè)命令:
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 顯示數(shù)據(jù)庫(kù)
(圖片來自網(wǎng)絡(luò))
3.6 初始化數(shù)據(jù)庫(kù)
在之前的篇章中,我們是定義的內(nèi)存配置數(shù)據(jù)實(shí)現(xiàn)的操作,而在本篇中,我們進(jìn)行數(shù)據(jù)持久化操作,可以將之前內(nèi)存的數(shù)據(jù)作為種子處理遷移到創(chuàng)建的數(shù)據(jù)庫(kù)中進(jìn)行初始化操作。
?參考文章: 用戶數(shù)據(jù)遷移
?3.6.1 創(chuàng)建文件
創(chuàng)建SeedData.cs文件,用于初始化基礎(chǔ)數(shù)據(jù):
????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();}}}配置內(nèi)容可以查看之前篇章內(nèi)容文件Config.cs 或者項(xiàng)目地址.
3.6.2 調(diào)用方法
然后我們可以從主入口Main方法調(diào)用它:
????????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 程序運(yùn)行
輸入 dotnet run /seed
3.6.4 效果
四、問題
4.1 提示找不到上下文
上面我們說到了的兩個(gè)上下文,如果我們直接通過執(zhí)行遷移命令是會(huì)報(bào)錯(cuò)的,比如我們直接遷移 PersistedGrantDbContext 上下文:
因?yàn)檫w移的目標(biāo)不匹配,需要更改遷移程序集,如
?options.UseSqlServer(connection, b => b.MigrationsAssembly("Ids4.EFCore"))
?所以,就需要在項(xiàng)目中配置對(duì)應(yīng)的服務(wù),我們?cè)?startup.cs 啟動(dòng)文件中,配置服務(wù) ConfigureService ,配置 EF 操作數(shù)據(jù)庫(kù).
解決方法 : 可參考上面的實(shí)踐部分中的「數(shù)據(jù)庫(kù)上下文」.
?獲取數(shù)據(jù)庫(kù)連接字符串
配置數(shù)據(jù)庫(kù)服務(wù)
4.2 dotnet ef 無法執(zhí)行
因?yàn)檎也坏街付ǖ拿罨蛭募?/p>
從 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另裝。命令如下:
?dotnet tool install --global dotnet-ef
?五、總結(jié)
簡(jiǎn)單介紹了「IdentityServer4」持久化存儲(chǔ)機(jī)制相關(guān)配置和操作數(shù)據(jù),實(shí)現(xiàn)了數(shù)據(jù)遷移,及應(yīng)用程序的實(shí)踐。
本篇未對(duì)用戶進(jìn)行持久化操作存儲(chǔ)說明,因?yàn)?strong>「IdentityServer4」本就支持了接入其他認(rèn)證方式,所以自己根據(jù)需要進(jìn)行合理「擴(kuò)展」的,比如我們可以使用 「Asp.Net Core 自帶的 Identity」 身份認(rèn)證機(jī)制來「實(shí)現(xiàn)擴(kuò)展」,當(dāng)然,你也可以自己定義相應(yīng)的操作,在后續(xù)篇章中會(huì)進(jìn)行說明介紹。
如果有不對(duì)的或不理解的地方,希望大家可以多多指正,提出問題,一起討論,不斷學(xué)習(xí),共同進(jìn)步。
項(xiàng)目地址
https://github.com/i3yuan/Yuan.IdentityServer4.Demo/tree/main/DiffAuthMode/EntityFrameworkStorage
六、附加
「EF支持持久化配置和操作數(shù)據(jù)」
總結(jié)
以上是生活随笔為你收集整理的IdentityServer4系列 | 支持数据持久化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 明源云·天际,地产⾏业的Salesfor
- 下一篇: BeetleX自定义http/webso