認證授權:IdentityServer4 - 資料持久化

cwsheng發表於2020-10-06

前言:

  前面的文章中IdentityServer4 配置內容都儲存到記憶體中,本篇文章開始把配置資訊儲存到資料庫中;本篇文章繼續基於github的程式碼來實現配置資料持久化到MySQL中

一、基於EFCore持久化IdentityServer資料

 1、資料庫上下文(DbContext )

   在前面使用IDS4時,配置的一些基礎:如Api資源、客戶端等資料;以及在使用過程中授權後發放的token、授權、授權碼等運算元據。如果持久化如何處理呢?IDS4已經提供了對應的方式 

    • ConfigurationDbContext

      主要負責資料庫對客戶端、標識資源、Api資源和CORS等的配置儲存

    • PersistedGrantDbContext 

       主要儲存運算元據,如:授權碼、訪問令牌、重新整理令牌等相關運算元據 

 2、在cz.IdentityServer中新增Nuget包:IdentityServer4.EntityFramework以及EF相關包

Install-Package IdentityServer4.EntityFramework
Install-Package Microsoft.EntityFrameworkCore
Install-Package Microsoft.EntityFrameworkCore.Tools
Install-Package Microsoft.EntityFrameworkCore.Design
Install-Package Pomelo.EntityFrameworkCore.MySql 

 3、修改Startup檔案中ConfigureServices方法中IdentityServer4配置內容如下:

public class Startup
{

    private IConfiguration _configuration;
    public Startup(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    // This method gets called by the runtime. Use this method to add services to the container.
    // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();

        services.Configure<CookiePolicyOptions>(options =>
        {
            options.MinimumSameSitePolicy = SameSiteMode.Strict;
        });
     //獲取連線串
        string connString = _configuration.GetConnectionString("Default");
     string migrationsAssembly = Assembly.GetEntryAssembly().GetName().Name; //新增IdentityServer服務 services.AddIdentityServer() //新增這配置資料(客戶端、資源) .AddConfigurationStore(opt => { opt.ConfigureDbContext = c => { c.UseMySql(connString, sql => sql.MigrationsAssembly(migrationsAssembly)); }; }) //新增運算元據(codes、tokens、consents) .AddOperationalStore(opt => { opt.ConfigureDbContext = c => { c.UseMySql(connString, sql => sql.MigrationsAssembly(migrationsAssembly)); }; //token自動清理 opt.EnableTokenCleanup = true; ////token自動清理間隔:預設1H //opt.TokenCleanupInterval=3600; ////token自動清理每次數量 //opt.TokenCleanupBatchSize = 100;
})
        //使用者預設依舊採用記憶體使用者,可用Identity替換
       .AddTestUsers(InMemoryConfig.Users().ToList());
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
    
//初始化資料(內容後面描述)
     SeedData.InitData(app);
if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseRouting();

        app.UseStaticFiles();
        app.UseCookiePolicy();
        app.UseIdentityServer();

        app.UseAuthentication();
        //使用預設UI,必須新增
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
        });
    }
}

 4、遷移資料

  遷移方式有多種方式:

  1、開啟包控制檯,執行以下命令:

1 add-migration InitialPersistedGrantDb -c PersistedGrantDbContext -o Migrations/IdentityServer/PersistedGrantDb 
2 add-migration InitialConfigurationDb -c ConfigurationDbContext -o Migrations/IdentityServer/ConfigurationDb
3 update-database -c PersistedGrantDbContext   
4 update-database -c ConfigurationDbContext   

 

 

    2、在專案路徑中執行命令列:

1 dotnet ef migrations add InitialPersistedGrantDb -c PersistedGrantDbContext -o Migrations/IdentityServer/PersistedGrantDb
2 dotnet ef migrations add InitialConfigurationDb -c ConfigurationDbContext -o Migrations/IdentityServer/ConfigurationDb
3 dotnet ef database update -c PersistedGrantDbContext
4 dotnet ef database update -c ConfigurationDbContext  

 

二、資料表含義

    資料結構遷移完成我們來看下建立了那些表:

   

  根據不同的資料庫上下文劃分如下圖:

  

三、初始化資料

  1、建立檔案SeedData.cs檔案用於初始化基礎資料:

public class SeedData
{
    public static void InitData(IApplicationBuilder serviceProvider)
    {
        Console.WriteLine("開始建立初始化資料...");
        using (var scope = serviceProvider.ApplicationServices.CreateScope())
        {
            scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
            {
                var context = scope.ServiceProvider.GetRequiredService<ConfigurationDbContext>();
                context.Database.Migrate();
                EnsureSeedData(context);
            }
        }
        Console.WriteLine("初始化資料建立完成.");
    }

    private static void EnsureSeedData(ConfigurationDbContext context)
    {
        if (!context.Clients.Any())
        {
            Console.WriteLine("Clients 正在初始化");
            foreach (var client in InMemoryConfig.GetClients())
            {
                context.Clients.Add(client.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            Console.WriteLine("IdentityResources 正在初始化");
            foreach (var resource in InMemoryConfig.GetIdentityResources())
            {
                context.IdentityResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.ApiResources.Any())
        {
            Console.WriteLine("ApiResources 正在初始化");
            foreach (var resource in InMemoryConfig.GetApiResources())
            {
                context.ApiResources.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }

        if (!context.ApiScopes.Any())
        {
            Console.WriteLine("ApiScopes 正在初始化");
            foreach (var resource in InMemoryConfig.GetApiScopes())
            {
                context.ApiScopes.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }
    }
}

 

  2、並在Startup檔案中新增:

 //初始化資料(內容後面描述)
SeedData.InitData(app);

 

  程式執行如下: 

  

 

 

  3、初始化主要資料結果如下圖:

  

 

 4、執行效果同上一篇文章效果相同

  

 四、其他

  本篇主要介紹了簡單使用IdentityServer4.EntityFramework持久化儲存相關配置資料和運算元據;本篇中使用者資訊未持久化儲存未介紹,因為IdentityServer4本就支援了接入其他認證方式,如 : NetCore 官方的 Identity,可以快速實現使用者管理。

  Github:https://github.com/cwsheng/IdentityServer.Demo 

相關文章