代码改变世界

IdentityServer4 搭建

2021-03-27 12:07  qgbo  阅读(186)  评论(0编辑  收藏  举报

环境 .net5

1. 安装dotnet 工具:

dotnet new -i IdentityServer4.Templates
dotnet tool install --global dotnet-ef

mkdir tmp,

cd tml

dotnet new is4ef

 

 

这会生成支持 EFCode的项目,项目名称是当前文件夹的名称 tmp。默认是Sqlite数据库。

里面包含 一个QuickStart的文件夹,用以显示界面。

迁移文件都生成好了。

直接运行,会初始化数据库,并能看到界面,登录成功!

2. 切换SQL Server 数据库。


dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design
修改StartUp.cs的ConfigurationService方法,部分代码如下
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
var connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddIdentityServer()
    .AddTestUsers(TestUsers.Users)
    .AddConfigurationStore(options =>
    {
        options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
            sql => sql.MigrationsAssembly(migrationsAssembly));
    })
    .AddOperationalStore(options =>
    {
        options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
            sql => sql.MigrationsAssembly(migrationsAssembly));
    });

执行如下命令,生成迁移代码:

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

这会有2个Context,

PersistedGrantDbContext 下面有2个集合 DeviceCodes  PersistedGrants,用于临时操作数据,如授权代码和刷新令牌等
public class PersistedGrant
    {
        public PersistedGrant();
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Key { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Type { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> SubjectId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> SessionId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> ClientId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> DateTime CreationTime { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> DateTime? Expiration { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> DateTime? ConsumedTime { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Data { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
}

public class DeviceFlowCodes
{
public DeviceFlowCodes();

    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the device code.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The device code.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> DeviceCode { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the user code.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The user code.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> UserCode { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the subject identifier.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The subject identifier.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> SubjectId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the session identifier.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The session identifier.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> SessionId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the client identifier.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The client identifier.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> ClientId { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets the description the user assigned to the device being authorized.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The description.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Description { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the creation time.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The creation time.</span>
    <span style="color: #0000ff;">public</span> DateTime CreationTime { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the expiration.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The expiration.</span>
    <span style="color: #0000ff;">public</span> DateTime? Expiration { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 摘要:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     Gets or sets the data.
    </span><span style="color: #008000;">//</span>
    <span style="color: #008000;">//</span><span style="color: #008000;"> 值:
    </span><span style="color: #008000;">//</span><span style="color: #008000;">     The data.</span>
    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">string</span> Data { <span style="color: #0000ff;">get</span>; <span style="color: #0000ff;">set</span><span style="color: #000000;">; }
}</span></pre>
View Code

 


剩下的都是Configration 的,用于配置数据,如Client,Apiresouce,scopes等
public DbSet<Client> Clients { get; set; }
        //
        // 摘要:
        //     Gets or sets the clients' CORS origins.
        //
        // 值:
        //     The clients CORS origins.
        public DbSet<ClientCorsOrigin> ClientCorsOrigins { get; set; }
        //
        // 摘要:
        //     Gets or sets the identity resources.
        //
        // 值:
        //     The identity resources.
        public DbSet<IdentityResource> IdentityResources { get; set; }
        //
        // 摘要:
        //     Gets or sets the API resources.
        //
        // 值:
        //     The API resources.
        public DbSet<ApiResource> ApiResources { get; set; }
        //
        // 摘要:
        //     Gets or sets the API scopes.
        //
        // 值:
        //     The API resources.
        public DbSet<ApiScope> ApiScopes { get; set; }
View Code

 

此时如果运行,会发生找不到数据库的错误,下面改动是代码生成数据库:

private void InitializeDatabase(IApplicationBuilder app)
{
    using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
    {
        serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
    var context = serviceScope.ServiceProvider.GetRequiredService&lt;ConfigurationDbContext&gt;();
    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.ApiScopes.Any())
    {
        foreach (var resource in Config.ApiScopes)
        {
            context.ApiScopes.Add(resource.ToEntity());
        }
        context.SaveChanges();
    }
}

}

 

运行,应该可以看到界面了。

如果有错误,检查当前的项目版本,是不是 .Net5, 然后确保Nuget 包是最近的