IdentityServer4系列 | 支持数据持久化

一、前言

在前面的篇章介绍中,一些基础配置如API资源、客户端资源等数据以及使用过程中发放的令牌等操作数据,我们都是通过将操作数据和配置数据存储在内存中进行实现的,而在实际开发生产中,我们需要考虑如何处理数据持久化呢?

这时「IdentityServer4」具有良好的扩展性,其中一个可扩展点是用于「IdentityServer」所需数据的存储机制,进行持久化操作。

下面将如何配置「IdentityServer」以使用「EntityFramework」(EF)作为此数据的存储机制把这些数据存储到「Sql Server」数据库, 这样更符合我们实际生产环境的需求。

二、初识

在我们的 「IdentityServer4」中官方定义的两个上下文,是有两种类型的数据需要持久化到数据库中:

1、「配置数据」(资源、客户端、身份);//这里是对应配置上下文 ConfigurationDbContext

2、「IdentityServer」在使用时产生的 「操作数据」(令牌,代码和用户的授权信息consents);//这里是对应操作上下文 PersistedGrantDbContext

「这两个上下文以及对应的数据模型,已经被 IdentityServer4 官方给封装好了」, 我们不需要做额外的操作,直接进行迁移即可使用。

2.1 ConfigurationDb

ConfigurationDbContext (IdentityServer configuration data) —— 负责数据库中对客户端、资源和 CORS 设置的配置存储;

如果需要从 EF 支持的数据库加载客户端、标识资源、API 资源或 CORS 数据 (而不是使用内存中配置), 则可以使用配置存储。此支持提供 IClientStoreIResura StoreICorsPolicyService 扩展性点的实现。这些实现使用名为 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  configvar 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 securebuilder.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 PersistedGrantDbContext4、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 操作数据库.

解决方法 : 可参考上面的实践部分中的「数据库上下文」.

  1. 获取数据库连接字符串

  2. 配置数据库服务

4.2 dotnet ef 无法执行

因为找不到指定的命令或文件

从 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另装。命令如下:

dotnet tool install --global dotnet-ef

五、总结

  1. 简单介绍了「IdentityServer4」持久化存储机制相关配置和操作数据,实现了数据迁移,及应用程序的实践。

  2. 本篇未对用户进行持久化操作存储说明,因为「IdentityServer4」本就支持了接入其他认证方式,所以自己根据需要进行合理「扩展」的,比如我们可以使用 「Asp.Net Core 自带的 Identity」 身份认证机制来「实现扩展」,当然,你也可以自己定义相应的操作,在后续篇章中会进行说明介绍。

  3. 如果有不对的或不理解的地方,希望大家可以多多指正,提出问题,一起讨论,不断学习,共同进步。

  4. 项目地址

https://github.com/i3yuan/Yuan.IdentityServer4.Demo/tree/main/DiffAuthMode/EntityFrameworkStorage

六、附加

「EF支持持久化配置和操作数据」

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306096.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言修仙受控可看吗,强推三本神奇到爆的小说,c语言修仙,程序员与修真会擦出什么火花...

大家好&#xff0c;我是小龙。今天我给大家推荐三本神奇到爆的小说&#xff0c;c语言修仙&#xff0c;程序员与修真会擦出什么火花!一《c语言修仙》【一十四洲】【简介】: 林浔是一个程序员&#xff0c;通宵编代码后发现自己身体内多了一个程序输入窗口。他尝试编了一个循环程序…

【Vue】Vue与ASP.NET Core WebAPI的集成

SPA单页面应用已经遍地开花&#xff0c;熟知的三大框架&#xff0c;Angular、Vue和React&#xff0c;其中Angular与React均可集成至ASP.NET Core&#xff0c;且提供了相关了中间件。但是Vue没有:“As far as I’m aware, we don’t have plans to introduce Vue-specific featu…

引入Jaeger——封装

随着微服务的普及&#xff0c;微服务间的调用全链路跟踪也火了起来&#xff0c;Jaeger(https://www.jaegertracing.io/)是CNCF孵化的全链路跟踪型项目&#xff0c;在.net core中&#xff0c;提供了一个Jaeger的Nuget(https://github.com/jaegertracing/jaeger-client-csharp)包…

c语言歌手预测成绩,5个裁判可以对10个歌手进行打分,计算各个歌手的最终得分排列...

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼if(flag0){printf("\n歌手信息为空&#xff0c;请利用键盘输入或文件读入&#xff01;\n\n");printf("按任意键返回......");getchar(); getchar();}fpfopen("c:\\backup1.txt","w");for(…

BeetleX自定义http/websocket压测用例视频

虽然BeetleX扩展了tcp/websocket/webapi压测工具(工具下载可以访问https://github.com/beetlex-io/TCPBenchmarks)&#xff0c;但测试工具都是针对消息定义来进行测试&#xff0c;很难整合完整的业务流程&#xff1b;如果能写代码那BeetleX组件提供一个测试组件可以更好地完成针…

临近年关,发生两起磁盘占满引发的服务下线故障

一口气说两个因为磁盘空间不足引发的应用故障。作为拿起键盘一把梭的Coder&#xff0c; 开发--->部署-->收工--->心旷神怡&#xff0c;滋一口82年的可乐.过了几个月&#xff0c;服务突然下线了&#xff01;CTO又有杀程序员祭天的理由了!事故1&#xff1a;Azure App Se…

c语言幼儿园积木游戏,幼儿园《积木游戏》课件【三篇】

【导语】课件制作本身就是作者综合素养的一种体现&#xff0c;它显现出制作者对教育、教学、教材改革方向的把握&#xff0c;对课堂教学的理解&#xff0c;对现代教育技术的领悟。因此教师在设计课件时一定要吃透教学内容&#xff0c;设计出符合教学的方案用于课件。下面是无忧…

c语言 listview,C语言 SDK编程之通用控件的使用--ListView

一、ListView控件属于通用控件CONTROL中的一种&#xff0c;在SDK编程方式时要使用通用控件必须包含comctl32.dll&#xff0c;所以代码中要有头文件: commctrl.h 导入库&#xff1a;comctl32.lib在使用通用控件之前应该先调用InitCommonControls();初始化它以ListView控件为例…

蚂蚁调度AntJob-分布式任务调度系统

分布式任务调度系统&#xff0c;纯NET打造的重量级大数据实时计算平台&#xff0c;万亿级调度经验积累&#xff01;面向中小企业大数据分析场景。开源地址&#xff1a;https://github.com/NewLifeX/AntJob使用教程&#xff1a;https://www.yuque.com/smartstone/blood/antjob体…

c语言怎么让图形界面单独显示,「分享」C语言如何编写图形界面

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼贴吧内经常有人问C语言是不是只能用于字符终端界面开发&#xff0c;不能用于图形界面。大家也都有回答&#xff0c;需要其他的库。MFC&#xff0c;GTK&#xff0c;QT。本人近期刚用GTK库加上纯C写成了第一个LINUX实用程序。现在与大…

如何在 ASP.NET Core 中 自定义中间件

ASP.NET Core 是一个跨平台&#xff0c;开源的&#xff0c;轻量级&#xff0c;高性能 并且高度模块化的web框架&#xff0c;同时扩展性也是非常强&#xff0c;你可以在 request -> response 请求管道中安插各种中间件来根据自己的场景定制化&#xff0c;比如说&#xff1a;监…

c语言电报关系的题目,c语言所有题目以跟答案.doc

c语言所有题目以跟答案判断题关系运算符<与的优先级相同。 N2.7&312的值是15. N3.在TurboC中&#xff0c;整型数据在内存中占2个字节。 YC语言本身不提供输入输出语句&#xff0c;输入输出操作是由函数实现的。 Y5.char [ ]“Very good”:是一个合法的为字符串数组赋值的…

ASP.NET Core Authentication and Authorization

最近把一个Asp .net core 2.0的项目迁移到Asp .net core 3.1&#xff0c;项目启动的时候直接报错:InvalidOperationException: Endpoint CoreAuthorization.Controllers.HomeController.Index (CoreAuthorization) contains authorization metadata, but a middleware was not …

android dialog 自定义布局,如何设置AlertDialog的自定义布局?

调用我的对话框:alertDialog showInfoDialog(message "$wrongPasscodeMessage\n$retryMessage")方法如下:fun FragmentActivity.showInfoDialog(message: String?): AlertDialog? {return try {val customLayout layoutInflater.inflate(R.layout.custom_layout…

ASP.NET Core 依赖注入-集成 Autofac

概述ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式&#xff0c;这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术。默认服务容器是 Microsoft.Extensions.DependencyInjection 。内置的服务容器一般能满足简单的框架和部分消费者应用的需求。 建议使用内置容器&…

android 打开谷歌导航,国内开启google位置记录功能/android版google maps 7+上,恢复位置记录功能在国内使用(需root)...

android版google 地图在 7以后的版本上&#xff0c;位置记录功能在国内不能用了&#xff0c;提示本功能不能在中国使用。至少对本人&#xff0c;“位置记录”功能是非常有用的功能&#xff0c;尤其是骑车出行时记录自己的路线。目前还没找到替代产品。之前一段时间内恢复回旧版…

程序员过关斩将--少年派登录安全的奇幻遐想

“据说&#xff0c;这篇也是快餐&#xff0c;完全符合年轻人口味说到登录&#xff0c;无人不知无人不晓。每一个有用户体系的相关系统都会有登录的入口&#xff0c;登录是为了确认操作人的正确性。说到登录安全&#xff0c;其实是一个很伟大的命题&#xff0c;不过常用的手段也…

gif android 点击 加载,android 加载显示gif图片的解决方案

使用方法&#xff1a;1-把GifView.jar加入你的项目。2-在xml中配置GifView的基本属性&#xff0c;GifView继承自View类&#xff0c;和Button、ImageView一样是一个UI控件。如&#xff1a;android:layout_height"wrap_content"android:layout_width"wrap_content…

C# 9 新特性 —— 增强的 foreach

C# 9 新特性 —— 增强的 foreachIntro在 C# 9 中增强了 foreach 的使用&#xff0c;使得一切对象都有 foreach 的可能我们来看一段代码&#xff0c;这里我们试图遍历一个 int 类型的值思考一下&#xff0c;我们可以怎么做使得上面的代码编译通过呢&#xff1f;迭代器模式迭代器…

android系统休眠发广播,Android - BroadcastReceiver

BroadcastReceiverBroadcastReceiver&#xff0c;广播接收者&#xff0c;用来接收系统和应用的广播&#xff0c;并做出相应的处理&#xff0c;如电量过低时提示用户充电等&#xff1b;BroadcastReceiver 是 Android 的四大组件之一&#xff0c;分为 普通广播、有序广播、粘性广…