Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
一、前言
上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完美,之后我经过自己的学习查阅并阅读了相关源代码,发现 IdentityServer4 可以实现自定义GrantType 授权方式。
声明:看这篇文章时如果你没有阅读我上一篇 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,那请先移步看上面的文章,再来看这篇文章会更加清晰,感谢支持,感谢关注!
二、场景模拟
上篇文章已经把电商系统从单一网关架构升级到多网关架构,架构图如下:

然而上面的授权中心 使用的是密码授权模式,但是对于微信小程序、微信公众号商城端使用的授权还不是很合适;
微信小程序和微信公众号微商城客户端的场景如下:
用户访问小程序商城或者微信公众号商城后会到微信服务端获得授权拿到相关的用户openId、unionId、userName 等相关信息,再携带openId、unionId、userName等信息访问授权中心网关,进行授权,如果不存在则自动注册用户,如果存在则登录授权成功等操作。那这个场景后我该如何改造授权中心服务网关呢?经过研究和探讨,我把上面的架构图细化成如下的网关架构图:

三、授权中心改造升级
上一篇文章中我们的解决方案中已经建立了三个项目:
Jlion.NetCore.Identity.Service:授权中心网关 -WebApi项目Jlion.NetCore.Identity.UserApiService:用户业务网关-WebApi项目Jlion.NetCore.Identity:基础类库,主要用于把公共的基础设施层放到这一块
通过上面的需求场景分析,我们目前的授权中心还不够这种需求,故我们可以通过IdentityServer4 自定义授权方式进行改造升级来满足上面的场景需求。
经过查看源代码我发现我们可以通过实现IExtensionGrantValidator抽象接口进行自定义授权方式来实现,并且实现ValidateAsync 方法,
现在我在之前的解决方案授权中心项目中新增WeiXinOpenGrantValidator类代码如下:
public class WeiXinOpenGrantValidator : IExtensionGrantValidator
{
public string GrantType => GrantTypeConstants.ResourceWeixinOpen;
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
try
{
#region 参数获取
var openId = context.Request.Raw[ParamConstants.OpenId];
var unionId = context.Request.Raw[ParamConstants.UnionId];
var userName = context.Request.Raw[ParamConstants.UserName];
#endregion
#region 通过openId和unionId 参数来进行数据库的相关验证
var claimList = await ValidateUserAsync(openId, unionId);
#endregion
#region 授权通过
//授权通过返回
context.Result = new GrantValidationResult
(
subject: openId,
authenticationMethod: "custom",
claims: claimList.ToArray()
);
#endregion
}
catch (Exception ex)
{
context.Result = new GrantValidationResult()
{
IsError = true,
Error = ex.Message
};
}
}
#region Private Method
/// <summary>
/// 验证用户
/// </summary>
/// <param name="loginName"></param>
/// <param name="password"></param>
/// <returns></returns>
private async Task<List<Claim>> ValidateUserAsync(string openId, string unionId)
{
//TODO 这里可以通过openId 和unionId 来查询用户信息(数据库查询),
//我这里为了方便测试还是直接写测试的openId 相关信息用户
var user = OAuthMemoryData.GetWeiXinOpenIdTestUsers();
if (user == null)
{
//注册用户
}
return new List<Claim>()
{
new Claim(ClaimTypes.Name, $"{openId}"),
};
}
#endregion
}
GrantTypeConstants 代码是静态类,主要用于定义GrantType的自定义授权类型,可能后续还有更多的自定义授权方式所以,统一放这里面进行管理,方便维护,代码如下:
public static class GrantTypeConstants
{
/// <summary>
/// GrantType - 微信端授权
/// </summary>
public const string ResourceWeixinOpen = "weixinopen";
}
ParamConstants 类主要是定义自定义授权需要的参数,代码如下:
public class ParamConstants
{
public const string OpenId = "openid";
public const string UnionId = "unionid";
public const string UserName = "user_name";
}
好了上面得自定义验证器已经实现了,但是还不够,我们还需要让客户端支持自定义的授权类型,我们打开OAuthMemoryData代码中的GetClients,代码如下:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client()
{
ClientId =OAuthConfig.UserApi.ClientId,
AllowedGrantTypes = new List<string>()
{
GrantTypes.ResourceOwnerPassword.FirstOrDefault(),//Resource Owner Password模式
GrantTypeConstants.ResourceWeixinOpen,//新增的自定义微信客户端的授权模式
},
ClientSecrets = {new Secret(OAuthConfig.UserApi.Secret.Sha256()) },
AllowedScopes= {OAuthConfig.UserApi.ApiName},
AccessTokenLifetime = OAuthConfig.ExpireIn,
},
};
}
客户端AllowedGrantTypes 配置新增了我刚刚自定义的授权方式GrantTypeConstants.ResourceWeixinOpen,
现在客户端的支持也已经配置好了,最后我们需要通过AddExtensionGrantValidator<>扩展方法把自定义授权验证器注册到DI中,代码如下:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
#region 数据库存储方式
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(OAuthMemoryData.GetApiResources())
//.AddInMemoryClients(OAuthMemoryData.GetClients())
.AddClientStore<ClientStore>()
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
.AddExtensionGrantValidator<WeiXinOpenGrantValidator>();
#endregion
}
好了,简单的授权中心代码升级已经完成,我们分别通过命令行运行授权中心和用户业务网关 ,之前的用户业务网关无需改动任何代码,运行图分别如下:
Jlion.NetCore.Identity.Server 授权中心运行如下
Jlion.NetCore.Identity.UserApiServer 用户业务网关运行如下
我们现在用postman模拟openId、unionId、userName参数来请求授权中心获得AccessToken,请求如下:

我们再通过postman 携带授权信息访问用户业务网关数据,结果图如下:

好了,自定义授权模式已经完成,简单的授权中心也已经升级完成,上面WeiXinOpenGrantValidator 验证器中我没有直接走数据库方式进行验证和注册,简单的写了个Demo ,大家有兴趣可以 把TODO那一快数据库的操作去实现,代码我已经提交到 github上了,这里再次分享下我博客同步实战的demo 地址 https://github.com/a312586670/IdentityServerDemo
四、思考与总结
本篇我介绍了自定义授权方式,通过查看源代码及查阅资料学习了IdentityServer4 可以通过自定义授权方式进行扩展。这样授权中心可以扩展多套授权方式,比如今天所分享的 自定义微信openId 授权、短信验证码授权等其他自定义授权,一套Api资源可以兼并多套授权模式,灵活扩展,灵活升级。本篇涉及的知识点不多,但是非常重要,因为我们在使用授权中心统一身份认证时经常会遇到多种认证方式的结合,和多套不同应用用户的使用,在掌握了授权原理后,就能在不同的授权方式中切换的游刃有余,到这里有的博友会问AccentToken 有过期时间,会过期怎么办?难道要重新授权一次吗?这些问题我会安排下一篇文章分享。
灵魂一问:
上面的授权中心 例子主要是为了让大家更好的理解自定义授权的使用场景及它的灵活性,真实的场景这样直接把 openId等相关信息来验证授权安全吗?大家可以可以思考下,如果不安全大家又有什么好的解决方案呢?自我提升在于不停的自我思考,大家可以敬请的发挥自己的思考,把答案留在留言板中,以供大家参考学习,感谢!!!
Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式的更多相关文章
- Asp.Net Core 中IdentityServer4 授权中心之应用实战
一.前言 查阅了大多数相关资料,查阅到的IdentityServer4 的相关文章大多是比较简单并且多是翻译官网的文档编写的,我这里在 Asp.Net Core 中IdentityServer4 的应 ...
- Asp.Net Core 中IdentityServer4 授权原理及刷新Token的应用
一.前言 上面分享了IdentityServer4 两篇系列文章,核心主题主要是密码授权模式及自定义授权模式,但是仅仅是分享了这两种模式的使用,这篇文章进一步来分享IdentityServer4的授权 ...
- Asp.Net Core 中IdentityServer4 实战之角色授权详解
一.前言 前几篇文章分享了IdentityServer4密码模式的基本授权及自定义授权等方式,最近由于改造一个网关服务,用到了IdentityServer4的授权,改造过程中发现比较适合基于Role角 ...
- Asp.Net Core 中IdentityServer4 实战之 Claim详解
一.前言 由于疫情原因,让我开始了以博客的方式来学习和分享技术(持续分享的过程也是自己学习成长的过程),同时也让更多的初学者学习到相关知识,如果我的文章中有分析不到位的地方,还请大家多多指教:以后我会 ...
- 从零搭建一个IdentityServer——聊聊Asp.net core中的身份验证与授权
OpenIDConnect是一个身份验证服务,而Oauth2.0是一个授权框架,在前面几篇文章里通过IdentityServer4实现了基于Oauth2.0的客户端证书(Client_Credenti ...
- asp.net Core 中AuthorizationHandler 实现自定义授权
前言 ASP.NET Core 中 继承的是AuthorizationHandler ,而ASP.NET Framework 中继承的是AuthorizeAttribute. 它们都是用过重写里面的方 ...
- ASP.Net Core 中使用Zookeeper搭建分布式环境中的配置中心系列一:使用Zookeeper.Net组件演示基本的操作
前言:马上要过年了,祝大家新年快乐!在过年回家前分享一篇关于Zookeeper的文章,我们都知道现在微服务盛行,大数据.分布式系统中经常会使用到Zookeeper,它是微服务.分布式系统中必不可少的分 ...
- 第十五节:Asp.Net Core中的各种过滤器(授权、资源、操作、结果、异常)
一. 简介 1. 说明 提到过滤器,通常是指请求处理管道中特定阶段之前或之后的代码,可以处理:授权.响应缓存(对请求管道进行短路,以便返回缓存的响应). 防盗链.本地化国际化等,过滤器用于横向处理业务 ...
- ASP.NET Core 中jwt授权认证的流程原理
目录 1,快速实现授权验证 1.1 添加 JWT 服务配置 1.2 颁发 Token 1.3 添加 API访问 2,探究授权认证中间件 2.1 实现 Token 解析 2.2 实现校验认证 1,快速实 ...
随机推荐
- K3CLOUD呼吸时间设置
- NI Vision 介绍
NI Vision主要包括三种主要软件包: 主程序包(Vision Acquisition Software), 视觉开发模块(Vision Development Module), 以及用于自动检测 ...
- django框架基础-视图系统-长期维护
################## 什么是视图? ####################### 视图: 1,一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受W ...
- Angular开发者指南(六)作用域
什么是作用域? 作用域是引用应用程序模型的对象. 它是表达式的执行上下文. 作用域以层次结构排列,模仿应用程序的DOM结构,它可以观察表达式和传播事件. 作用域的特征 Scope提供API($watc ...
- scarce|component|
ADJ-GRADED 缺乏的;不足的;供不应求的If something is scarce, there is not enough of it. Food was scarce and expen ...
- .js——alert()语句
在.js文件中,通过alert()语句可以生成弹出框,弹出框中的内容message部分可以是常量字符串,也可以是含有变量的字符串连接,下面举几个例子简要说明下: 1. 参数为常量字符串 alert(& ...
- labview学习——生产者/消费者(数据)(事件)
其主要的模型: 主要从以下几个方面理解: 1.可重入性 正常的labview是多线程设计语言,而我们在执行VI时的规则是通过VI的命名来分别调用实现的. 打开VI的Highlight调试工具,可以看出 ...
- Linux搭建nginx+php/php-fpm+mysql环境
百度内部php框架odp有单独的nginx+php/php-fpm环境,但为了更好的实践,自己搭建一套单独的. 1.首先安装nginx 两种方式: 1)yum源安装(使用root权限)yum inst ...
- Java中的字符串比较
在C++中,两个字符串比较的代码可以为: (string1==string2) 但是在java中,这个代码即使在两个字符串完全相同的情况下也会返回 false ,Java中必须使用 string1.e ...
- spring基于@Value绑定属Bean性失
用spring注解@Value绑定属性失败 环境: eclipse Version: Luna Release (4.4.0) spring 4.0 Junit4 其他依赖包 描述: JsrDAO类, ...

