identityserver mysql_IdentityServer4系列 | 支持数据持久化

原标题: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 数据 (而不是使用内存中配置), 则可以使用配置存储。此支持提供 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方法添加如下代码:

publicvoidConfigureServices( IServiceCollection services)

{

services.AddControllersWithViews;

varconnectionString = Configuration.GetConnectionString( "DataContext");

if(connectionString == "")

{

thrownewException( "数据库配置异常");

}

varmigrationsAssembly = typeof(Startup).GetTypeInfo.Assembly.GetName.Name;

// in DB config

varbuilder = 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

c67f78b0ae0d78a56d5a8ae34c6cfa2c.png

3.4.2 在命令窗口

方法二:

判断是否支持命令行迁移,你可以在项目所在的目录下打开一个命令 Power shell 并运行命令 dotnet ef, 它应该是这样的:

0e5adbeea055bfa9f43b1be0ce6a7205.png

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

d7dc5610449f40e9e960b5dd99104488.png

3.5 显示数据库

902fcfd13bb7f69b86330e917939fde8.png

7ee096aee0c3dc3c8517dc07f86a37d1.png

(图片来自网络)

3.6 初始化数据库

在之前的篇章中,我们是定义的内存配置数据实现的操作,而在本篇中,我们进行数据持久化操作,可以将之前内存的数据作为种子处理迁移到创建的数据库中进行初始化操作。

参考文章: 用户数据迁移

3.6.1 创建文件

创建SeedData.cs文件,用于初始化基础数据:

publicclassSeedData

{

publicstaticvoidEnsureSeedData( IServiceProvider serviceProvider)

{

Console.WriteLine( "Seeding database...");

using( varscope = serviceProvider.GetRequiredService.CreateScope)

{

scope.ServiceProvider.GetService.Database.Migrate;

varcontext = scope.ServiceProvider.GetRequiredService;

context.Database.Migrate;

EnsureSeedData(context);

}

Console.WriteLine( "Done seeding database.");

Console.WriteLine;

}

privatestaticvoidEnsureSeedData( ConfigurationDbContext context)

{

if(!context.Clients.Any)

{

Console.WriteLine( "Clients 正在初始化");

foreach( varclient inConfig.GetClients)

{

context.Clients.Add(client.ToEntity);

}

context.SaveChanges;

}

if(!context.IdentityResources.Any)

{

Console.WriteLine( "IdentityResources 正在初始化");

foreach( varresource inConfig.GetIdentityResources)

{

context.IdentityResources.Add(resource.ToEntity);

}

context.SaveChanges;

}

if(!context.ApiResources.Any)

{

Console.WriteLine( "ApiResources 正在初始化");

foreach( varresource inConfig.GetApiResources)

{

context.ApiResources.Add(resource.ToEntity);

}

context.SaveChanges;

}

if(!context.ApiScopes.Any)

{

Console.WriteLine( "ApiScopes 正在初始化");

foreach( varresource inConfig.GetApiScopes)

{

context.ApiScopes.Add(resource.ToEntity);

}

context.SaveChanges;

}

}

}

配置内容可以查看之前篇章内容文件Config.cs 或者项目地址.

3.6.2 调用方法

然后我们可以从主入口 Main 方法调用它:

publicstaticvoidMain( string[] args)

{

varseed = args.Contains( "/seed");

if(seed)

{

args = args.Except( new[] { "/seed"}).ToArray;

}

varhost = CreateHostBuilder(args).Build;

if(seed)

{

SeedData.EnsureSeedData(host.Services);

}

host.Run;

}

3.6.3 程序运行

输入 dotnet run /seed

2fcce6b13d85a1e36723a10feb044f3d.png

3.6.4 效果

5faf03003552ae2a454f1fcede8f4bb0.png

四、问题4.1 提示找不到上下文

上面我们说到了的两个上下文,如果我们直接通过执行迁移命令是会报错的,比如我们直接迁移 PersistedGrantDbContext 上下文:

2bd0e7cf31e78537ca3bca7193031694.png

因为迁移的目标不匹配,需要更改迁移程序集,如

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」身份认证机制来 「实现扩展」,当然,你也可以自己定义相应的操作,在后续篇章中会进行说明介绍。

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

项目地址

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

六、附加

「EF支持持久化配置和操作数据」返回搜狐,查看更多

责任编辑:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值