在前面的篇章介绍中,一些基础配置如API资源、客户端资源等数据以及使用过程当中发放的令牌等操做数据,咱们都是经过将操做数据和配置数据存储在内存中进行实现的,而在实际开发生产中,咱们须要考虑如何处理数据持久化呢?html
这时IdentityServer4具备良好的扩展性,其中一个可扩展点是用于IdentityServer所需数据的存储机制,进行持久化操做。git
下面将如何配置IdentityServer以使用EntityFramework(EF)做为此数据的存储机制把这些数据存储到Sql Server数据库, 这样更符合咱们实际生产环境的需求。github
在咱们的 IdentityServer4中官方定义的两个上下文,是有两种类型的数据须要持久化到数据库中:sql
一、配置数据(资源、客户端、身份);//这里是对应配置上下文
ConfigurationDbContext
shell二、IdentityServer在使用时产生的 操做数据(令牌,代码和用户的受权信息consents);//这里是对应操做上下文
PersistedGrantDbContext
数据库
这两个上下文以及对应的数据模型,已经被 IdentityServer4 官方给封装好了, 咱们不须要作额外的操做,直接进行迁移便可使用。json
ConfigurationDbContext
(IdentityServer configuration data) —— 负责数据库中对客户端、资源和 CORS 设置的配置存储;网络
若是须要从 EF 支持的数据库加载客户端、标识资源、API 资源或 CORS 数据 (而不是使用内存中配置), 则可使用配置存储。此支持提供 IClientStore
、IResura Store
和 ICorsPolicyService
扩展性点的实现。这些实现使用名为 ConfigurationDbContext
的 dbcontext 派生类对数据库中的表进行建模。antd
PersistedGrantDbContext
(IdentityServer operational data.) -—— 负责存储赞成、受权代码、刷新令牌和引用令牌;app
若是须要从 EF 支持的数据库 (而不是默认的内存数据库) 加载受权授予、赞成和令牌 (刷新和引用), 则可使用操做存储。此支持提供了 IPersistedGrantStore
扩展点的实现。实现使用名为 PersistedGrantDbContext
的 dbcontext 派生类对数据库中的表进行建模。
创建一个MVC的Asp.Net Core项目 ,使用MVC模板
IdentityServer4.EntityFramework
以及EF相关包
1.IdentityServer4 2.IdentityServer4.AspNetIdentity 3.IdentityServer4.EntityFramework
由于本文中使用的是SqlServer
数据库,因此须要安装对应的EF程序包对数据库的支持。
Microsoft.EntityFrameworkCore.SqlServer
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(); }
方法一:
须要添加EF工具,安装Microsoft.EntityFrameworkCore.Tools
, 进行迁移
一、add-migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/PersistedGrantDb 二、add-migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/ConfigurationDb 三、update-database -Context PersistedGrantDbContext 四、update-database -Context ConfigurationDbContext
方法二:
判断是否支持命令行迁移,你能够在项目所在的目录下打开一个命令 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
(图片来自网络)
在以前的篇章中,咱们是定义的内存配置数据实现的操做,而在本篇中,咱们进行数据持久化操做,能够将以前内存的数据做为种子处理迁移到建立的数据库中进行初始化操做。
参考文章: 用户数据迁移
建立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 或者项目地址.
而后咱们能够从主入口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(); }
输入 dotnet run /seed
上面咱们说到了的两个上下文,若是咱们直接经过执行迁移命令是会报错的,好比咱们直接迁移 PersistedGrantDbContext 上下文:
由于迁移的目标不匹配,须要更改迁移程序集,如
options.UseSqlServer(connection, b => b.MigrationsAssembly("Ids4.EFCore"))
因此,就须要在项目中配置对应的服务,咱们在 startup.cs 启动文件中,配置服务 ConfigureService ,配置 EF 操做数据库.
解决方法 : 可参考上面的实践部分中的数据库上下文.
获取数据库链接字符串
配置数据库服务
由于找不到指定的命令或文件
从 3.0 起,EF Core 命令列工具 (dotnet ef) 不在 .NET Core SDK 里面,需另装。命令以下:
dotnet tool install --global dotnet-ef