IdentityServer4一些概念记录
一:基础概念
1、什么是IdentityServer4
IdentityServer4是依赖于asp.net core来实现openId和oauth2.0协议的身份认证框架。
2、OpenId和OAuth2.0概念
要想理解这个之前,先看asp.net core中
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
...
app.UseAuthentication(); //认证,判断是否合法用户
app.UseAuthorization(); //授权,判断是否有具体功能合法操作权限
...
}
UseAuthentication在UseAuthorization之前
2.1、OpenId
关于这个解释网上有很多,我就不赘述了。按照我的理解,openId关注的是表明用户是谁。
2.2、OAuth2.0
OAuth更关注Authorization(授权)。
比如:
比如可以通过A网站授权B网站,获取A网站身份资源,如昵称、头像等信息。
3、IdentityServer4使用场景
- 单点登录,比如vue、react实现oidc功能
- 接口保护
- 支持openId登录
- 统一登录
- 自定义登录,比如接入微信的openId登录
4、IdentityServer4主要接口
4.1、获取配置
/.well-known/openid-configuration
4.2、获取加密密钥
/.well-known/openid-configuration/jwks
4.3、获取token
/connect/token
4.4、获取身份信息
/connect/userinfo
IdentityServer4(二)持久化
目录
- 一、简介
- 二、客户端(Clients)
- 三、接口资源(ApiResources)
- 四、接口作用域(ApiScopes)
- 五、身份资源(IdentityResources)
- 六、DeviceCodes
- 七、PersistedGrants
- 八、aspnet core使用IdentityServer4
一、简介
- 这里我对IdentityServer持久化配置中的数据库设计方案进行解释。
- 数据库使用的是mssql
二、客户端(Clients)

2.1 Clients客户端主表
| 是否开启秘钥校验 | |||||||||
| 6 | ClientName | nvarchar | 200 | 是 | 客户端名称 | ||||
| 7 | Description | nvarchar | 1000 | 是 | 客户端说明 | ||||
| 8 | ClientUri | nvarchar | 2000 | 是 | |||||
| 9 | LogoUri | nvarchar | 2000 | 是 | |||||
| 10 | RequireConsent | bit | 1 | ||||||
| 11 | AllowRememberConsent | bit | 1 | ||||||
| 12 | AlwaysIncludeUserClaimsInIdToken | bit | 1 | 始终允许token中包含用户声明信息 | |||||
| 13 | RequirePkce | bit | 1 | ||||||
| 14 | AllowPlainTextPkce | bit | 1 | ||||||
| 15 | RequireRequestObject | bit | 1 | ||||||
| 16 | AllowAccessTokensViaBrowser | bit | 1 | 是否允许浏览器传递token | |||||
| 17 | FrontChannelLogoutUri | nvarchar | 2000 | 是 | |||||
| 18 | FrontChannelLogoutSessionRequired | bit | 1 | ||||||
| 19 | BackChannelLogoutUri | nvarchar | 2000 | 是 | |||||
| 20 | BackChannelLogoutSessionRequired | bit | 1 | ||||||
| 21 | AllowOfflineAccess | bit | 1 | 是否允许离线工作,获取刷新令牌需要为true | |||||
| 22 | IdentityTokenLifetime | int | 身份令牌生命周期(单位:秒) | ||||||
| 23 | AllowedIdentityTokenSigningAlgorithms | nvarchar | 100 | 是 | |||||
| 24 | AccessTokenLifetime | int | 访问令牌生命周期(单位:秒) | ||||||
| 25 | AuthorizationCodeLifetime | int | 授权代码生命周期(单位:秒) | ||||||
| 26 | ConsentLifetime | int | 是 | 用户同意的生存期(单位:秒)。默认为null(无过期) | |||||
| 27 | AbsoluteRefreshTokenLifetime | int | 刷新令牌的最长生命周期(单位:秒) | ||||||
| 28 | SlidingRefreshTokenLifetime | int | 刷新令牌滑动过期时间(单位:秒) | ||||||
| 29 | RefreshTokenUsage | int | 刷新令牌使用次数(0-有效期内刷新令牌不变 1-刷新令牌用后即焚) | ||||||
| 30 | UpdateAccessTokenClaimsOnRefresh | bit | 1 | ||||||
| 31 | RefreshTokenExpiration | int | 刷新令牌过期方式(0-刷新令牌将在固定时间点到期(由AbsoluteRefreshTokenLifetime指定)1-刷新令牌时,将刷新刷新令牌的生命周期(按SlidingRefreshTokenLifetime中指定的数量)。生命周期不会超过AbsoluteRefreshTokenLifetime) | ||||||
| 32 | AccessTokenType | int | 授权token类型(0-Jwt;1-Reference) | ||||||
| 33 | EnableLocalLogin | bit | 1 | 登录UI是否呈现用户名/密码输入 | |||||
| 34 | IncludeJwtId | bit | 1 | ||||||
| 35 | AlwaysSendClientClaims | bit | 1 | ||||||
| 36 | ClientClaimsPrefix | nvarchar | 200 | 是 | 客户端声明类型前缀。默认为client_ | ||||
| 37 | PairWiseSubjectSalt | nvarchar | 200 | 是 | 此客户端用户在成对主体生成中使用的盐值 | ||||
| 38 | Created | datetime2 | 创建时间 | ||||||
| 39 | Updated | datetime2 | 是 | 更新时间 | |||||
| 40 | LastAccessed | datetime2 | 是 | 最后访问时间 | |||||
| 41 | UserSsoLifetime | int | 是 | 自上次用户身份验证以来的最长持续时间(单位:秒) | |||||
| 42 | UserCodeType | nvarchar | 100 | 是 | 设备流用户代码的类型 | ||||
| 43 | DeviceCodeLifetime | int | 设备代码生存期(单位:秒) | ||||||
| 44 | NonEditable | bit | 1 |
2.2 ClientClaims 客户端声明配置
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Type | nvarchar | 250 | ||||||
| 3 | Value | nvarchar | 250 | ||||||
| 4 | ClientId | int |
2.3 ClientCorsOrigins 客户端跨域配置
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Origin | nvarchar | 150 | ||||||
| 3 | ClientId | int |
2.4 ClientGrantTypes 客户端授权模式
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | GrantType | nvarchar | 250 | ||||||
| 3 | ClientId | int |
2.5 ClientIdPRestrictions(?这个我也不了解,项目中也没有用到)
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Provider | nvarchar | 200 | ||||||
| 3 | ClientId | int |
2.6 ClientPostLogoutRedirectUris 客户端允许登出回跳地址
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | PostLogoutRedirectUri | nvarchar | 2000 | 回跳地址,如:https://xxx/#/signout-callback-out,如果前端使用oidc登录,则需要配置 | |||||
| 3 | ClientId | int |
2.7 ClientProperties
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Key | nvarchar | 250 | ||||||
| 3 | Value | nvarchar | 2000 | ||||||
| 4 | ClientId | int |
2.8 ClientRedirectUris 客户端允许登录回跳地址
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | RedirectUri | nvarchar | 2000 | 回跳地址,如:https://xxx/#/signin-callback-in,如果前端使用oidc登录,则需要配置 | |||||
| 3 | ClientId | int |
2.9 ClientScopes
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Scope | nvarchar | 200 | ||||||
| 3 | ClientId | int |
2.10 ClientSecrets 客户端密钥
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Description | nvarchar | 2000 | 是 | 说明 | ||||
| 3 | Value | nvarchar | 4000 | 密钥(加密后) | |||||
| 4 | Expiration | datetime2 | 是 | 过期时间 | |||||
| 5 | Type | nvarchar | 250 | 类型(默认SharedSecret) | |||||
| 6 | Created | datetime2 | |||||||
| 7 | ClientId | int |
三、接口资源(ApiResources)

接口资源模型图
3.1 ApiResources接口资源主表
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Enabled | bit | 1 | ||||||
| 3 | Name | nvarchar | 200 | ||||||
| 4 | DisplayName | nvarchar | 200 | 是 | |||||
| 5 | Description | nvarchar | 1000 | 是 | |||||
| 6 | AllowedAccessTokenSigningAlgorithms | nvarchar | 100 | 是 | |||||
| 7 | ShowInDiscoveryDocument | bit | 1 | ||||||
| 8 | Created | datetime2 | |||||||
| 9 | Updated | datetime2 | 是 | ||||||
| 10 | LastAccessed | datetime2 | 是 | ||||||
| 11 | NonEditable | bit | 1 |
3.2 ApiResourceClaims接口资源声明表
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Type | nvarchar | 200 | ||||||
| 3 | ApiResourceId | int |
3.3 ApiResourceProperties接口资源性能表(?还没搞明白用来干啥的)
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Key | nvarchar | 250 | ||||||
| 3 | Value | nvarchar | 2000 | ||||||
| 4 | ApiResourceId | int |
3.4 ApiResourceScopes
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Scope | nvarchar | 200 | ||||||
| 3 | ApiResourceId | int |
3.5 ApiResourceSecrets
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Description | nvarchar | 1000 | 是 | |||||
| 3 | Value | nvarchar | 4000 | ||||||
| 4 | Expiration | datetime2 | 是 | ||||||
| 5 | Type | nvarchar | 250 | ||||||
| 6 | Created | datetime2 | |||||||
| 7 | ApiResourceId | int |
四、接口作用域(ApiScopes)

接口作用域模型图
4.1 ApiScopes
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Enabled | bit | 1 | ||||||
| 3 | Name | nvarchar | 200 | ||||||
| 4 | DisplayName | nvarchar | 200 | 是 | |||||
| 5 | Description | nvarchar | 1000 | 是 | |||||
| 6 | Required | bit | 1 | ||||||
| 7 | Emphasize | bit | 1 | ||||||
| 8 | ShowInDiscoveryDocument | bit | 1 |
4.2 ApiScopeClaims
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Type | nvarchar | 200 | ||||||
| 3 | ScopeId | int |
4.3 ApiScopeProperties
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Key | nvarchar | 250 | ||||||
| 3 | Value | nvarchar | 2000 | ||||||
| 4 | ScopeId | int |
五、身份资源(IdentityResources)

身份资源模型图
5.1 IdentityResources
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Enabled | bit | 1 | ||||||
| 3 | Name | nvarchar | 200 | ||||||
| 4 | DisplayName | nvarchar | 200 | 是 | |||||
| 5 | Description | nvarchar | 1000 | 是 | |||||
| 6 | Required | bit | 1 | ||||||
| 7 | Emphasize | bit | 1 | ||||||
| 8 | ShowInDiscoveryDocument | bit | 1 | ||||||
| 9 | Created | datetime2 | |||||||
| 10 | Updated | datetime2 | 是 | ||||||
| 11 | NonEditable | bit | 1 |
5.2 IdentityResourceClaims
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Type | nvarchar | 200 | ||||||
| 3 | IdentityResourceId | int |
5.3 IdentityResourceProperties
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Id | int | 是 | 是 | |||||
| 2 | Key | nvarchar | 250 | ||||||
| 3 | Value | nvarchar | 2000 | ||||||
| 4 | IdentityResourceId | int |
六、DeviceCodes
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | UserCode | nvarchar | 200 | 是 | |||||
| 2 | DeviceCode | nvarchar | 200 | ||||||
| 3 | SubjectId | nvarchar | 200 | 是 | |||||
| 4 | SessionId | nvarchar | 100 | 是 | |||||
| 5 | ClientId | nvarchar | 200 | ||||||
| 6 | Description | nvarchar | 200 | 是 | |||||
| 7 | CreationTime | datetime2 | |||||||
| 8 | Expiration | datetime2 | |||||||
| 9 | Data | nvarchar | -1 |
七、PersistedGrants
| 序号 | 列名 | 数据类型 | 长度 | 小数位数 | 主键 | 自增 | 允许空 | 默认值 | 列说明 |
|---|---|---|---|---|---|---|---|---|---|
| 1 | Key | nvarchar | 200 | 是 | |||||
| 2 | Type | nvarchar | 50 | ||||||
| 3 | SubjectId | nvarchar | 200 | 是 | |||||
| 4 | SessionId | nvarchar | 100 | 是 | |||||
| 5 | ClientId | nvarchar | 200 | ||||||
| 6 | Description | nvarchar | 200 | 是 | |||||
| 7 | CreationTime | datetime2 | |||||||
| 8 | Expiration | datetime2 | 是 | ||||||
| 9 | ConsumedTime | datetime2 | 是 | ||||||
| 10 | Data | nvarchar | max |
八、aspnet core使用IdentityServer4
8.1、生成证书文件
我这里使用的是OpenSSL进行生成的。
req -newkey rsa:2048 -nodes -keyout ids4.key -x509 -days 7300 -out ids4.cer
pkcs12 -export -in ids4.cer -inkey ids4.key -out ids4.pfx
8.2、写IdentityServer4持久化扩展方法
using IdentityServer4.EntityFramework.Stores;
using IdentityServer4.Stores;
using Ids4.Admin.IdentityServer.Validator;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace Ids4.Admin.IdentityServer.ConfigureServicesExtensions
{
public static class ServiceCollectionExtension
{
public static IServiceCollection AddIdentityServerPrdExtension(this IServiceCollection services, IConfiguration configuration)
{
var dbServer = configuration["Apptions:DBServer"];
return dbServer switch
{
"mssql" => AddIdentityServerPrdExtension_MsSql(services, configuration),
"mysql" => AddIdentityServerPrdExtension_MySql(services, configuration),
_ => AddIdentityServerPrdExtension_MsSql(services, configuration),
};
}
#region IdentityServer4 配置 MsSql版
/// <summary>
/// 注册生产环境IdentityServer4配置
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
private static IServiceCollection AddIdentityServerPrdExtension_MsSql(IServiceCollection services, IConfiguration configuration)
{
//读取证书,我这里使用的pfx证书,可以使用openssl
var fileName = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, configuration["PfxSettings:Path"]);
if (!File.Exists(fileName))
{
throw new FileNotFoundException("签名证书文件未找到!");
}
var cert = new X509Certificate2(fileName, configuration["PfxSettings:Pwd"]);
var connectionString = configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddSigningCredential(cert)
//客户端及资源数据库存储配置
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = context =>
context.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
//令牌及授权码数据库存储配置
.AddOperationalStore(options =>
{
options.ConfigureDbContext = context =>
context.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// 自动清理过期token.
options.EnableTokenCleanup = true;
})
.AddConfigurationStoreCache()//这里使用了内存缓存,避免每次授权都要进行读库
.AddResourceOwnerValidator<LoginValidator>()//这里是我实现的自定义用户名密码登陆器
.AddExtensionGrantValidator<WeiXinOpenGrantValidator>();//这里是我实现的自定义微信openId登陆器
services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
return services;
}
#endregion
#region IdentityServer4 配置 MySql版
/// <summary>
/// 注册生产环境IdentityServer4配置
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
private static IServiceCollection
