前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【One by One系列】IdentityServer4(八)使用EntityFramework Core对数据进行持久化

【One by One系列】IdentityServer4(八)使用EntityFramework Core对数据进行持久化

作者头像
DDGarfield
发布2022-06-23 17:07:08
1.1K0
发布2022-06-23 17:07:08
举报
文章被收录于专栏:加菲的博客加菲的博客

上几篇,我们创建了客户端,scope,启动时,IdentityServer把这些配置数据加载至内存,但是,如果我们想要更改配置,就必须停掉IdentityServer,然后重新启动。且IdentityServer在运行过程中还会生成临时数据,如授权码、是否同意的按钮选择、以及refresh token。默认情况下,这些也存储在内存中。

将以上这些数据存储在数据库中进行数据持久化,方便重启跨多个IdentityServer实例,这个持久化,我们可以使用IdentityServer4 Entity Framework

除了手动配置EF支持之外,还有一个IdentityServer模板可以使用,dotnet new is4ef创建一个支持EF的新项目。

IdentityServer4.EntityFrameworknuget包实现了所需的存储和服务,主要使用以下两个DbContexts:

  • ConfigurationDbContext - 作用于注册数据,如客户端,资源,scope等等
  • PersistedGrantDbContext - 作用于临时操作数据,如授权码,refresh tokens

这些context适用于任何ef core兼容的关系型数据库,sqlserver,mysql。

可以在

  • IdentityServer4.EntityFramework.Storage包中找到contextentitiesIdentityServer4 stores
  • IdentityServer4.EntityFramework包括了注册的扩展方法,且包括了IdentityServer4.EntityFramework.Storage

1.添加nuget引用

代码语言:javascript
复制
cd .\IdentityServer\
dotnet add package IdentityServer4.EntityFramework

2.添加对mysql的支持

代码语言:javascript
复制
dotnet add package MySql.Data.EntityFrameworkCore

3.数据迁移

IdentityServer4.EntityFramework.Storage包存在包含映射自IdentityServer模型的实体类,随着IdentityServer的模型的更改,IdentityServer4.EntityFramework.Storage中的实体类也将更改,所以需要使用者随着时间的推移,升级使用这个包,这个过程,需要负责在数据库架构以及在实体类更改时,对该数据库架构进行必要的更改。最好的方式就是使用EF数据迁移(EF migrations)

这里官方只提供了针对sqlserver的sql脚本,可以看一下,做个了解。

4.重新配置存储

Startup.cs

代码语言:javascript
复制
using Microsoft.EntityFrameworkCore;
using System.Reflection; //这里用到了反射

var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;

//3308为宿主机端口,映射docker mysql容器默认端口3306
const string connectionString = @"Persist Security Info=False;database=IdentityServer4;server=localhost;port=3308;Connect Timeout=30;user id=root; pwd=123456";

services.AddIdentityServer()
    .AddTestUsers(TestUsers.Users)
    .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = b => b.UseMySQL(connectionString,
                        sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = b => b.UseMySQL(connectionString,
                        sql => sql.MigrationsAssembly(migrationsAssembly));
                });

因为我们在IdentityServer.csproj中使用EF迁移,所以通过对MigrationsAssembly的调用来告诉Entity Framework 的宿主项目(IdentityServer.csproj)将包含迁移代码(the migrations code)。这是必要的,因为宿主项目(IdentityServer.csproj)与包含DbContext类的项目,两者是位于不同的程序集中(IdentityServer4.EntityFramework.Storage)。

5.创建迁移

一旦将IdentityServer配置为使用 Entity Framework Core,我们将需要生成一些迁移-migrations。

Entity Framework Core CLI

Microsoft.EntityFrameworkCore.Design nuget包

代码语言:javascript
复制
#安装ef core 工具
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

#cd到IdentityServer项目目录
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb


dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb

温故而知新:还记得在VS的Package Manager Console是如何执行命令创建迁移的吗?

代码语言:javascript
复制
#第一步

Add-Migration InitialCreate

#第二步

Update-Database

6.初始化数据库

现在我们已经完成了迁移,我们可以编写代码从迁移-migrations创建数据库。我们还可以使用在前面的quickstart中定义的内存配置数据来为数据库初始化种子,当然这个seed最好只是在调试环境下执行。

官方提示:在这个快速入门中使用的方法主要是使IdentityServer更容易启动和运行。您应该设计适合自己体系结构的数据库创建和维护策略。

在Startup.cs中增加下面的初始化方法:

代码语言:javascript
复制
using System.Linq;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();

        var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
        context.Database.Migrate();
        if (!context.Clients.Any())
        {
            foreach (var client in Config.Clients)
            {
                context.Clients.Add(client.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            foreach (var resource in Config.IdentityResources)
            {
                context.IdentityResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.ApiResources.Any())
        {
            foreach (var resource in Config.Apis)
            {
                context.ApiResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }
    }
}

public void Configure(IApplicationBuilder app)
{
    // this will do the initial DB population
    InitializeDatabase(app);

    // the rest of the code that was already here
    // ...
}

上面的InitializeDatabase方法可以方便地 seed the database,但是这种方法在每次运行应用程序时都留进去执行并不理想。一旦填充数据库初始化数据之后,就可以考虑删除对其之调用。

7.运行客户端应用

这个就简略些,上个命令即可

代码语言:javascript
复制
cd src\IdentityServer
dotnet run
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 加菲的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.添加nuget引用
  • 2.添加对mysql的支持
  • 3.数据迁移
  • 4.重新配置存储
  • 5.创建迁移
  • 6.初始化数据库
  • 7.运行客户端应用
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档