目录
- 一、简介
- 二、客户端(Clients)
- 三、接口资源(ApiResources)
- 四、接口作用域(ApiScopes)
- 五、身份资源(IdentityResources)
- 六、DeviceCodes
- 七、PersistedGrants
- 八、aspnet core使用IdentityServer4
一、简介
- 这里我对IdentityServer持久化配置中的数据库设计方案进行解释。
- 数据库使用的是mssql
二、客户端(Clients)
客户端数据模型图
2.1 Clients客户端主表
序号 |
列名 |
数据类型 |
长度 |
小数位数 |
主键 |
自增 |
允许空 |
默认值 |
列说明 |
1 |
Id |
int |
|
|
是 |
是 |
|
|
主键Id |
2 |
Enabled |
bit |
1 |
|
|
|
|
|
是否有效 |
3 |
ClientId |
nvarchar |
200 |
|
|
|
|
|
客户端Id |
4 |
ProtocolType |
nvarchar |
200 |
|
|
|
|
|
协议类型(oidc、wsfed、saml2p) |
5 |
RequireClientSecret |
bit |
1 |
|
|
|
|
|
是否开启秘钥校验 |
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 客户端允许登出回跳地址
2.7 ClientProperties
序号 |
列名 |
数据类型 |
长度 |
小数位数 |
主键 |
自增 |
允许空 |
默认值 |
列说明 |
1 |
Id |
int |
|
|
是 |
是 |
|
|
|
2 |
Key |
nvarchar |
250 |
|
|
|
|
|
|
3 |
Value |
nvarchar |
2000 |
|
|
|
|
|
|
4 |
ClientId |
int |
|
|
|
|
|
|
|
2.8 ClientRedirectUris 客户端允许登录回跳地址
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 AddIdentityServerPrdExtension_MySql(IServiceCollection services, IConfiguration configuration)
{
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("MySqlConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer()
.AddSigningCredential(cert)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = context =>
context.UseMySql(connectionString, new MySqlServerVersion(new Version("5.7")),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddOperationalStore(options =>
{
options.ConfigureDbContext = context =>
context.UseMySql(connectionString, new MySqlServerVersion(new Version("5.7")),
sql => sql.MigrationsAssembly(migrationsAssembly));
// 自动清理过期token.
options.EnableTokenCleanup = true;
})
.AddConfigurationStoreCache()//这里使用了内存缓存,避免每次授权都要进行读库
.AddResourceOwnerValidator<LoginValidator>()
.AddExtensionGrantValidator<WeiXinOpenGrantValidator>();
services.AddTransient<IPersistedGrantStore, PersistedGrantStore>();
return services;
}
#endregion
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServerPrdExtension(Configuration);//注册IdentityServer4持久化
}
8.3、自定义登录验证器
8.3.1 密码模式验证器
官方或者各大百度找到的示例,几乎都是使用IdentityServer4的TestUser,在生产中,这种写法肯定不行。上述代码中有LoginValidator,这个就是我自定义的密码登录验证器,主要功能就是替换默认的密码模式登录。
/// <summary>
/// 密码模式验证器
/// </summary>
/// <remarks>需要继承IResourceOwnerPasswordValidator,在注册IdentityServer4时,通过AddResourceOwnerValidator注册验证器</remarks>
public class LoginValidator : IResourceOwnerPasswordValidator
{
private readonly ISystemService _systemService;
public LoginValidator(ISystemService systemService)
{
_systemService = systemService;
}
public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
//用户密码登录,这个可以自己实现
var (userInfo, errMsg) = await _systemService.LgoinAsync(new LoginReques()
{
Account = context.UserName,
Password = context.Password,
});
context.Result = UserGrantResult.GetGrantValidationResult(userInfo, errMsg);
}
}
public class UserGrantResult
{
public static GrantValidationResult GetGrantValidationResult(LoginResponse user, string errMsg = "")
{
if (user != null)
{
Claim[] claims = new Claim[] {
new Claim("employeeId",user.EmployeeId.ToString()),
new Claim("tenantId",user.TenantId.ToString()),
//这里可以写自己所需的claim
};
return new GrantValidationResult(subject: user.EmployeeId.ToString(), authenticationMethod: "custom", claims: claims);
}
else
{
return new GrantValidationResult(TokenRequestErrors.InvalidRequest, string.IsNullOrWhiteSpace(errMsg) ? "用户名或密码错误" : errMsg);
}
}
}
8.3.2 自定义微信登录模式
有些业务可能会需要微信一键登录吧,IdentityServer4可以通过自定义扩展授权模式,来实现微信openId的一键登录
/// <summary>
/// 微信授权验证
/// </summary>
/// <remarks>需要继承IExtensionGrantValidator,在注册IdentityServer4时,通过AddExtensionGrantValidator注册验证器</remarks>
public class WeiXinOpenGrantValidator : IExtensionGrantValidator
{
private readonly IUserService _userService;
public WeiXinOpenGrantValidator(IUserService userService)
{
_userService = userService;
}
public string GrantType => "wechatopen";//定义微信登录模式名称
/// <summary>
/// 验证器
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
try
{
#region 获取参数
var appid = context.Request.Raw["appid"];//微信AppId
var openId = context.Request.Raw["openid"];//用户OpenId
var phone = context.Request.Raw["phone"];//用户手机号码
#endregion
var (userInfo, errMsg) = await _userService.QueryAccountByWechatOpenIdAsync(appid, openId, phone);//自定义微信登录方法
context.Result = UserGrantResult.GetGrantValidationResult(userInfo, errMsg);
}
catch (Exception ex)
{
context.Result = new GrantValidationResult()
{
IsError = true,
Error = ex.Message
};
}
}
}
参考8.2,注册IdentityServer4持久化时,将自定义验证器也注册进去就行。
8.4 客户端使用IdentityServer4
8.4.1 API使用IdentityServer4
public static IServiceCollection AddIds4Client_API(this IServiceCollection services, ApiAuthenticationModel model)
{
ervices.AddAuthorization();
ervices.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
/*===========================================
这里填的是签名颁发机构地址,会调用//.well-known/openid-configuration/jwks 获取签名服务器公钥,
是通过访问/.well-known/openid-configuration,获取到所需信息
===========================================*/
options.Authority = model.Authority;
options.RequireHttpsMetadata = model.RequireHttpsMetadata; //是否开启https
options.ApiName = model.ApiName; //api的name,
options.ApiSecret = model.ApiSecret;//api密钥
});
return services;
}
public class ApiAuthenticationModel
{
/// <summary>
/// 验证地址
/// </summary>
public string Authority { get; set; }
/// <summary>
/// 是否Https请求
/// </summary>
public bool RequireHttpsMetadata { get; set; }
/// <summary>
/// 客户端ID名称
/// </summary>
public string ApiName { get; set; }
/// <summary>
/// 客户端密钥
/// </summary>
public string ApiSecret { get; set; }
}
终
接下来会开一篇新的文章,讲述各种IdentityServer4配置关系
网友评论