一、前言

上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,其中有不少博友给我提了问题,其中有一个博友问我的一个场景,我给他解答的还不够完美,之后我经过自己的学习查阅并阅读了相关源代码,发现 IdentityServer4 可以实现自定义GrantType 授权方式。

声明:看这篇文章时如果你没有阅读我上一篇 Asp.Net Core 中IdentityServer4 授权中心之应用实战 的文章,那请先移步看上面的文章,再来看这篇文章会更加清晰,感谢支持,感谢关注!

二、场景模拟

上篇文章已经把电商系统从单一网关架构升级到多网关架构,架构图如下:

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

三、授权中心改造升级

通过上面的需求场景分析,我们目前的授权中心还不够这种需求,故我们可以通过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模拟openIdunionIduserName参数来请求授权中心获得AccessToken,请求如下:

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

好了,自定义授权模式已经完成,简单的授权中心也已经升级完成,上面WeiXinOpenGrantValidator验证器中我没有直接走数据库方式进行验证和注册,简单的写了个Demo ,大家有兴趣可以 把TODO那一快数据库的操作去实现,代码我已经提交到 github上了,这里再次分享下我博客同步实战的demo 地址 https://github.com/a312586670/IdentityServerDemo

四、思考与总结

本篇我介绍了自定义授权方式,通过查看源代码及查阅资料学习了IdentityServer4 可以通过自定义授权方式进行扩展。这样授权中心可以扩展多套授权方式,比如今天所分享的 自定义微信openId 授权、短信验证码授权等其他自定义授权,一套Api资源可以兼并多套授权模式,灵活扩展,灵活升级。本篇涉及的知识点不多,但是非常重要,因为我们在使用授权中心统一身份认证时经常会遇到多种认证方式的结合,和多套不同应用用户的使用,在掌握了授权原理后,就能在不同的授权方式中切换的游刃有余,到这里有的博友会问AccentToken 有过期时间,会过期怎么办?难道要重新授权一次吗?这些问题我会安排下一篇文章分享。

灵魂一问:

上面的授权中心 例子主要是为了让大家更好的理解自定义授权的使用场景及它的灵活性,真实的场景这样直接把 openId等相关信息来验证授权是不安全的,也是不建议的。大家可以思考下为什么不安全?那么要解决这个安全问题大家又有什么好的解决方案呢?自我提升在于不停的自我思考,大家可以敬请的把自己想到的解决方案留在下面,以供大家参考学习,感谢!!!

欢迎大家微信扫码关注【dotNET博士】公众号

dotNET博士

静默授权获取unionid_Asp.Net Core 中IdentityServer4 授权中心之自定义授权相关推荐

  1. .net授权获取openid_Asp.Net Core 中IdentityServer4 授权中心之自定义授权

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

  2. Asp.Net Core 中IdentityServer4 实战之角色授权详解

    一.前言 前几篇文章分享了IdentityServer4密码模式的基本授权及自定义授权等方式,最近由于改造一个网关服务,也用到了IdentityServer4的授权,改造过程中发现比较适合基于Role ...

  3. Asp.Net Core 中IdentityServer4 实战之 Claim详解

    一.前言 由于疫情原因,让我开始了以博客的方式来学习和分享技术(持续分享的过程也是自己学习成长的过程),同时也让更多的初学者学习到相关知识,如果我的文章中有分析不到位的地方,还请大家多多指教:以后我会 ...

  4. Asp.Net Core 中IdentityServer4 授权流程及刷新Token

    一.前言 上面分享了IdentityServer4 两篇系列文章,核心主题主要是密码授权模式及自定义授权模式,但是仅仅是分享了这两种模式的使用,这篇文章进一步来分享IdentityServer4的授权 ...

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

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

  6. Asp.Net Core 中IdentityServer4 授权中心之应用实战

    一.前言 查阅了大多数相关资料,搜索到的IdentityServer4 的应用文章大多是比较简单并且多是翻译官网的文档编写的,我这里在 Asp.Net Core 中IdentityServer4 的应 ...

  7. ASP.NET Core 中如何通过 AuthorizeAttribute 做自定义验证?

    咨询区 jltrem: 我想在 ASP.NET Core 中用 authorization 特性实现一个自定义验证,在之前的版本中,我可以用系统提供的 bool AuthorizeCore(HttpC ...

  8. ASP.NET Core WebAPI中使用JWT Bearer认证和授权

    为什么是 JWT Bearer ASP.NET Core 在 Microsoft.AspNetCore.Authentication 下实现了一系列认证, 包含 Cookie, JwtBearer,  ...

  9. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第一部分:微信授权获取基本信息的介绍 我们首先来看看官方的文档怎么说: 如果用户在微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑. 关于网页授权回调域 ...

最新文章

  1. IOS 笔试题(二)
  2. python的软件叫什么-Python 是什么软件?
  3. python是不是特别垃圾-Python 这语言真是混乱和原始
  4. 物料创建更新相关Table
  5. 【emWin】例程六:设置颜色
  6. TCP中间件_个人方案
  7. python 3 一些常用的内置数据结构介绍
  8. php中常见的header类型
  9. spring基础——<bean>scope属性
  10. 【干货】这样写总结年终奖翻倍!
  11. javascript 检测密码强度 美化版
  12. 拓端tecdat|R语言中实现广义相加模型GAM和普通最小二乘(OLS)回归
  13. java applet init_java applet init start
  14. WebView网页打不开原因之一(及自己遇到的一些WebView问题记录)
  15. 什么是Oncall?
  16. 洛谷P4238 多项式乘法逆元
  17. 新网站关键词优化小技巧
  18. Ubuntu 设置合上笔记本盖子休眠的方法
  19. verdi/debussy的快捷键 以及基本操作
  20. 如何整理碎片化的知识?

热门文章

  1. freeSWITCH 视频通话
  2. CentOS7 NTP server + keepalived
  3. JS中比較2个字符串内元素的不同(字符1, 字符2, 分隔符可选)
  4. php数组的几个函数和超全局变量
  5. 【论文写作】客户端设计与实现中模块程序实现如何写
  6. php的布局设计,php学习之div+css布局设计排版(六)
  7. 进程与服务的签名_服务器被黑客攻击后如何查找溯源攻击
  8. mysql flaskalchemy_FlaskSQLAlchemy声明性和MySQL特定的数据类型
  9. SQL Server 2014 导入Excel
  10. Run-Time Check Failure #2 – Stack around the variable 'a' was corrupted.