IdentityServer4除了提供常规的几种授权模式外(AuthorizationCode、ClientCredentials、Password、RefreshToken、DeviceCode),还提供了可以拓展的授权模式,下面就根据源码简单说下IdentityServer4是如何实现自定义授权模式的。

一、查看IdentityServer4自定义授权模式源码

当用户请求 connect/token 地址时,会执行TokenRequestValidator类的ValidateRequestAsync方法,在ValidateRequestAsync方法中根据GrantTypes类型调用不同的Validate方法,如下:

public async Task<TokenRequestValidationResult> ValidateRequestAsync(NameValueCollection parameters, ClientSecretValidationResult clientValidationResult)
{
//去掉了部分代码。。。 _validatedRequest.GrantType = grantType; switch (grantType)
{
case OidcConstants.GrantTypes.AuthorizationCode:
return await RunValidationAsync(ValidateAuthorizationCodeRequestAsync, parameters);
case OidcConstants.GrantTypes.ClientCredentials:
return await RunValidationAsync(ValidateClientCredentialsRequestAsync, parameters);
case OidcConstants.GrantTypes.Password:
return await RunValidationAsync(ValidateResourceOwnerCredentialRequestAsync, parameters);
case OidcConstants.GrantTypes.RefreshToken:
return await RunValidationAsync(ValidateRefreshTokenRequestAsync, parameters);
case OidcConstants.GrantTypes.DeviceCode:
return await RunValidationAsync(ValidateDeviceCodeRequestAsync, parameters);
default:
return await RunValidationAsync(ValidateExtensionGrantRequestAsync, parameters);
}
}

自定义的授权模式会进入 ValidateExtensionGrantRequestAsync 方法 ,方法中会做一些简单的验证,然后调用 _extensionGrantValidator.ValidateAsync 方法,_extensionGrantValidator.ValidateAsync方法实现如下:

public class ExtensionGrantValidator
{
private readonly ILogger _logger;
private readonly IEnumerable<IExtensionGrantValidator> _validators;//可以注入多个自定义授权类,用集合保存 /// <summary>
/// Initializes a new instance of the <see cref="ExtensionGrantValidator"/> class.
/// </summary>
/// <param name="validators">The validators.</param>
/// <param name="logger">The logger.</param>
public ExtensionGrantValidator(IEnumerable<IExtensionGrantValidator> validators, ILogger<ExtensionGrantValidator> logger)
{
if (validators == null)
{
_validators = Enumerable.Empty<IExtensionGrantValidator>();
}
else
{
//把注入的自定义授权类放入集合中
_validators = validators;
} _logger = logger;
} /// <summary>
/// 得到所有可用的自定义授权类型
/// </summary>
/// <returns></returns>
public IEnumerable<string> GetAvailableGrantTypes()
{
return _validators.Select(v => v.GrantType);
} /// <summary>
/// Validates the request.
/// </summary>
/// <param name="request">The request.</param>
/// <returns></returns>
public async Task<GrantValidationResult> ValidateAsync(ValidatedTokenRequest request)
{
//根据用户请求的GrantType获取自定义授权类
var validator = _validators.FirstOrDefault(v => v.GrantType.Equals(request.GrantType, StringComparison.Ordinal)); if (validator == null)
{
_logger.LogError("No validator found for grant type");
return new GrantValidationResult(TokenRequestErrors.UnsupportedGrantType);
} try
{
_logger.LogTrace("Calling into custom grant validator: {type}", validator.GetType().FullName); var context = new ExtensionGrantValidationContext
{
Request = request
};
//执行验证方法,这里执行的就是我们自定义授权的验证方法
await validator.ValidateAsync(context);
return context.Result;
}
catch (Exception e)
{
_logger.LogError(, e, "Grant validation error: {message}", e.Message);
return new GrantValidationResult(TokenRequestErrors.InvalidGrant);
}
}
}

二、实现自定义授权

比如我们想实现短信登录,就可以自定义一个授权类型 SMSGrantType

1、创建自定义授权类 SMSGrantValidator  ,实现IExtensionGrantValidator接口

public class SMSGrantValidator : IExtensionGrantValidator
{
public string GrantType => ExtensionGrantTypes.SMSGrantType; public Task ValidateAsync(ExtensionGrantValidationContext context)
{
var smsCode = context.Request.Raw.Get("smsCode");
var phoneNumber = context.Request.Raw.Get("phoneNumber"); if (string.IsNullOrEmpty(smsCode) || string.IsNullOrEmpty(phoneNumber))
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
} if (phoneNumber == "" && smsCode == "")
{
List<Claim> claimList = new List<Claim>();
claimList.Add(new Claim("userID", "")); context.Result = new GrantValidationResult(
subject: phoneNumber,
authenticationMethod: ExtensionGrantTypes.SMSGrantType,
claims: claimList);
}
else
{
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
"短信码错误!"
);
}
return Task.FromResult(); }
}

2、在Startup中注入SMSGrantValidator

services.AddIdentityServer()
//配置证书
.AddDeveloperSigningCredential()
//配置API资源
.AddInMemoryApiResources(Config.GetApis())
//配置身份资源
.AddInMemoryIdentityResources(Config.GetIdentityResources())
//预置Client
.AddInMemoryClients(Config.GetClients())
//自定义登录返回信息
.AddProfileService<ProfileService>()
//添加Password模式下用于自定义登录验证
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
//添加自定义授权模式
.AddExtensionGrantValidator<SMSGrantValidator>();

3、配置Client

//自定义短信验证模式
new Client
{
ClientId = "sms",
ClientName = "sms",
ClientSecrets = { new Secret("".Sha256()) },
AccessTokenLifetime = *,//单位s
AllowedGrantTypes = new[] {ExtensionGrantTypes.SMSGrantType}, //一个 Client 可以配置多个 GrantType
SlidingRefreshTokenLifetime = ,
AllowOfflineAccess = true,
AllowedScopes = new List<string>
{
"FrameworkAPI",//对应webapi里面的scope配置
StandardScopes.OfflineAccess,
StandardScopes.OpenId,
StandardScopes.Profile
}
}

用postman测试,返回token,测试成功

IdentityServer4 自定义授权模式的更多相关文章

  1. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

    一.前言 上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完 ...

  2. IdentityServer4(客户端授权模式)

    1.新建三个项目 IdentityServer:端口5000 IdentityAPI:端口5001 IdentityClient: 2.在IdentityServer项目中添加IdentityServ ...

  3. OAuth + Security - 6 - 自定义授权模式

    我们知道OAuth2的官方提供了四种令牌的获取,简化模式,授权码模式,密码模式,客户端模式.其中密码模式中仅仅支持我们通过用户名和密码的方式获取令牌,那么我们如何去实现一个我们自己的令牌获取的模式呢? ...

  4. 认证授权:IdentityServer4 - 各种授权模式应用

    前言: 前面介绍了IdentityServer4 的简单应用,本篇将继续讲解IdentityServer4 的各种授权模式使用示例 授权模式: 环境准备 a)调整项目结构如下:   b)调整cz.Id ...

  5. Spring Security OAuth2 微服务认证中心自定义授权模式扩展以及常见登录认证场景下的应用实战

    一. 前言 [APP 移动端]Spring Security OAuth2 手机短信验证码模式 [微信小程序]Spring Security OAuth2 微信授权模式 [管理系统]Spring Se ...

  6. IdentityServer4 实现自定义 GrantType 授权模式

    OAuth 2.0 默认四种授权模式(GrantType): 授权码模式(authorization_code) 简化模式(implicit) 密码模式(password) 客户端模式(client_ ...

  7. 【.NET Core项目实战-统一认证平台】第十四章 授权篇-自定义授权方式

    [.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何强制令牌过期的实现,相信大家对IdentityServer4的验证流程有了更深的了解,本篇我将介绍如何使用自定义的授权方 ...

  8. 一看就懂的IdentityServer4认证授权设计方案

    查阅了大多数相关资料,总结设计一个IdentityServer4认证授权方案,我们先看理论,后设计方案. 1.快速理解认证授权 我们先看一下网站发起QQ认证授权,授权通过后获取用户头像,昵称的流程. ...

  9. IdentityServer4 (1) 客户端授权模式(Client Credentials)

    写在前面 1.源码(.Net Core 2.2) git地址:https://github.com/yizhaoxian/CoreIdentityServer4Demo.git 2.相关章节 2.1. ...

随机推荐

  1. Python基础-语法知识

    ——编程语言的发展史 机器语言 优点:执行速度够快 缺点:开发效率非常低 汇编语言 优点:执行效率相较于机器语言略低 缺点:开发效率相较于机器语言略高 高级语言 C.C++.C#.java.PHP.p ...

  2. Win10 连接CentOS 8 的Docker容器中 SqlServer数据库

    楔子 工作在win10环境下,使用Docker Windows桌面版容器化SqlServer数据库连接使用(主要是想用Docker),但是同时需要Linux系统测试,win10 下VMware 虚拟机 ...

  3. 学习笔记42_SpringMVC

    SpringMVC中,Global.axas发生变化,其中 1.原来是 public class MvcApplication:System.web.HttpApplication 现在是 publi ...

  4. OV5640摄像头的数据处理配置流程(一)

    module RGB_init( //系统信号输入(时钟+复位) input cmos_clk_i, //模块控制时钟 input rst_n_i, //系统复位信号 //OV5640输出信号(从56 ...

  5. 深度学习tensorflow实战笔记(2)图像转换成tfrecords和读取

    1.准备数据 首选将自己的图像数据分类分别放在不同的文件夹下,比如新建data文件夹,data文件夹下分别存放up和low文件夹,up和low文件夹下存放对应的图像数据.也可以把up和low文件夹换成 ...

  6. NOIP模拟测试6

    看题目就知道这是一个悲伤的故事... 但还有更悲伤的 考崩了,难以描述. T1把数据范围看成2^12,我TM也是够了... T2思路接近正解,但不知道想了个神魔东西跑了N遍dijstra T3最狗了, ...

  7. STL.h

    最近老是被系统的一些STL卡到飞起,然后就手打了一个STL.h 库函数还没有打完,以后打新的还会再更,大家也可以使用,顺便帮我找一下bug,然后我再改进! template< typename ...

  8. python的变量内存管理

    一.变量的引用机制 当你在python中定义一个值,如x = 500时,python会在内存中开辟一个小地方用于存储数值. x = 500 #定义一个变量 print(id(x)) #打印该变量的内存 ...

  9. JSON数据与Java对象的相互转换

    JSON数据与Java对象的相互转换 JSON解析器 常见的解析器:Jsonlib .Gson. fastjson. jackson JSON转化为Java对象 使用步骤: 1.导入jackson的相 ...

  10. ajax传出数组到后台

    var vote = new Array();    $("input[name='option_name']").each(function(i){        if($(th ...