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. fenby C语言 P12

    条件语句的嵌套 注意格式对齐 #include <stdio.h> int main(){ int score=67; if(score<=100&&score> ...

  2. dom 创建时间

    下面讲述如何在页面生成一个装有日期的盒子 首先写出一个日期的函数进行赋值使用document.createElement创建一个文档节点div,然后将时间函数输出在div之中,利用document.b ...

  3. day3------基本数据类型int, bool, str,list,tuple,dict

    基本数据类型(int, bool, str,list,tuple,dict) 一.python基本数据类型 1. int  整数. 主要用来进行数学运算 2. str  字符串, 可以保存少量数据并进 ...

  4. leetcode算法小题(1)

    题目描述: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数 ...

  5. Docker 从入门到掉坑

    Docker 介绍 简单的对docker进行介绍,可以把它理解为一个应用程序执行的容器.但是docker本身和虚拟机还是有较为明显的出入的.我大致归纳了一下,可以总结为以下几点: docker自身也有 ...

  6. 解决本地无法访问vm虚拟机上centos7服务器中已配置好的hugo站点的问题

    一.配置VM网络连接 打开vm,找到"编辑",打开"虚拟网络编辑器" 选中下面截图中的上方为类型为"NAT模式"那一栏,然后点击下方的&qu ...

  7. python items和setdefault函数

    items() dict = {'runoob': '菜鸟教程', 'google': 'Google 搜索'} print("Value : %s" % dict.setdefa ...

  8. 7.22 NOIP模拟7

    又是炸掉的一次考试 T1.方程的解 本次考试最容易骗分的一道题,但是由于T2花的时间太多,我竟然连a+b=c都没判..暴力掉了40分. 首先a+b=c,只有一组解. 然后是a=1,b=1,答案是c-1 ...

  9. NOIP模拟测试13

    考得还算可以,T3还有提升空间(没看清题&&样例没过 拿了4分). 期望得分:80+40+0=120 实际得分:80+85+4=169 一脸黑线.....是数据比较水的原因,T2分都比 ...

  10. 【转载】InstantRun 原理——深度剖析 AndroidStudio 2.0

    一.前言 Android Studio 2.0开始支持 Instant Run 特性, 使得在开发过程中能快速将代码变化更新到设备上.之前,更新代码之后需要先编译一个完整的新Apk,卸载设备上已安装的 ...