【Blog.Core开源】网关自定义认证鉴权与传参

书接上文,上回咱们说到了《【Blog.Core开源】网关统一集成下游服务文档》,已经将多个下游服务统一集成到了网关里,并且也把接口文档Swagger给集成了,那今天就说一下认证和鉴权相关的话题。

355a73eefe1c3b600ae550af94b24aca.png

继续说下故事背景

在平时开发的时候,特别是有网关的情况下,经常会遇到一个不可避免的话题,就是网关到底要不要帮下游处理某些业务逻辑的问题,比如说认证鉴权、审计日志、当前用户信息获取,白名单等等。

这里其实见仁见智,同时也要考虑各个项目的具体架构设计和需要,我个人的习惯还是网关要轻一些,什么叫轻一些呢,拿BlogCore举例,认证走的是Ids4的统一认证平台,从平台那里得到令牌Token,然后经过网关走到BlogCore,解析,并走具体的自定义授权逻辑,因为这里涉及到动态菜单权限配置,所以很少会放到网关里处理,毕竟每个下游服务都可能会有自己的那部分逻辑。其实除了授权这块,还有一些数据,比如当前用户的私密信息,例如手机号之类的,这个phone肯定不能放到token里的,因为token虽然有过期时间,但是就算是失效,还是可以解密出来的,放到公网上的令牌基本都是只放一些非私密的个人信息,比如uid或者是roleId,实在有需要也可以在token里放部门的id的,这也无可厚非,但是phone和address是万万不能放到token里的。

那么问题来了,phone和address我们到底应该从哪里获取?上边的菜单权限大家已经达成共识,就是放到下游,让下游服务自己来处理,那根据token中的uid来获取phone信息,就需要考虑下了,很多人说放网关呗,每次请求查库等操作,然后放到header里传递给下游,这也是一个方案,今天也会给大家讲讲怎么获取,怎么传。

当然我个人的意见还是网关仅仅是解析token里有的,传递给下游,至于查库的那些,还是下游获取吧,这是我的个人意见,并不是完全正确。为什么呢,大家想想,咱们在网关里写拦截器或者中间件,每次接口请求,都根据header中的token来查库,这样不管下游需不需要,不管下游接口是不是匿名都去查库一下,会造成资源浪费,比如我就想搜索下list,每次都查询下当前人的user信息,似乎没那么必要,特别是list页面高并发的时候,是不是不太好,当然这样的好处就是对下游方便且能做详细的审计日志。

今天咱们就说下如何自定义拦截器传递自定义claim信息给下游。

01

PART

网关自定义认证处理器

在网关中注册认证服务,并设计处理器,实现认证授权拦截,比如说token是否可以正常的解密等,用来判断token的有效性等,也可以查询数据库,获取私密信息:

services.AddAuthentication().AddScheme<AuthenticationSchemeOptions, CustomAuthenticationHandler>(Permissions.GWName, _ => { });

然后具体的处理器,大家根据需求自定义即可,注意把信息放到Claims里,不仅可以在当前网关的其他地方获取,从而减少二次请求的情况。也可以传递给下游服务。

public class CustomAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{public CustomAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options,ILoggerFactory logger,UrlEncoder encoder,ISystemClock clock) : base(options, logger, encoder, clock){}protected override async Task<AuthenticateResult> HandleAuthenticateAsync(){// 可以查询数据库等操作// 获取当前用户不能放到token中的私密信息var userPhone = "15010000000";var claims = new List<Claim>(){new Claim("user-phone", userPhone),new Claim("gw-sign", "gw")};var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, Scheme.Name));var ticket = new AuthenticationTicket(principal, Scheme.Name);await Task.CompletedTask;return AuthenticateResult.Success(ticket);}
}

 内容很简单,就是一个普通的处理器,那接下来就是看如何把Claim给传给下游服务了。

02

PART

对下游服务开启认证处理器

Ocelot已经做好了配置,就像是自定义响应处理器一样,认证的也可以直接配置:

// blog-svc
{"UpstreamPathTemplate": "/svc/blog/{url}","UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],"LoadBalancerOptions": {"Type": "RoundRobin"},"DownstreamPathTemplate": "/svc/blog/{url}","DownstreamScheme": "http","DownstreamHostAndPorts": [{"Host": "localhost","Port": 9291}],// 直接配置认证Key即可"AuthenticationOptions": {"AuthenticationProviderKey": "GW"}
},

也可以有更多的参数配置,具体可以参考官网:

https://ocelot.readthedocs.io/en/latest/features/configuration.html?highlight=AuthenticationOptions#configuration

03

PART

Ocelot将Claim传递下游

还是在Ocelot的官网上可以看到很多Demo,我只配置三项,1、分别是动态从Claim中获取并用Request的Header传值,2、直接在Request中传递固定Header值,3、获取下游服务的Response的Header给上游网关。

其中第三点还是很有用的,比如我们以后的Skywalking中,如果某次链路请求报错了,但是又想快速的定位,所以就需要用户给我们提供当前操作的标识,有时候是uid,有时候是url,这两个都不是很直观。通过配置Ocelot,正好可以从下游服务的response的header中返给前端,用户就能提供了,更加快速方便的定位问题。

// blog-svc
{"UpstreamPathTemplate": "/svc/blog/{url}","UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],"LoadBalancerOptions": {"Type": "RoundRobin"},"DownstreamPathTemplate": "/svc/blog/{url}","DownstreamScheme": "http","DownstreamHostAndPorts": [{"Host": "localhost","Port": 9291}],// 添加到headers// 从claims中获取"AddHeadersToRequest": {"user-phone": "Claims[user-phone] > value","gw-sign": "Claims[gw-sign] > value"},// 从上游网关的request的header中"UpstreamHeaderTransform": {"custom-key": "blog.gateway"},// 从下游服务的response的header中"DownstreamHeaderTransform": {"down-app": "{para-down-app}","trace-id": "Trace-Id"},"AuthenticationOptions": {"AuthenticationProviderKey": "GW"}
},

在上边注释的三块,就是常见的三种方案。

04

PART

下游服务查看具体效果

在BlogCore服务中,valueController中测试下是否传递了具体的参数:

[HttpGet]
public MessageModel<List<ClaimDto>> MyClaims()
{return new MessageModel<List<ClaimDto>>(){success = true,response = (_user.GetClaimsIdentity().ToList()).Select(d =>new ClaimDto{Type = d.Type,Value = d.Value}).ToList()};
}

其中获取Claim方法,也获取了下header中其他的参数:

public IEnumerable<Claim> GetClaimsIdentity(){var claims = _accessor.HttpContext.User.Claims.ToList();var headers = _accessor.HttpContext.Request.Headers;foreach (var header in headers){claims.Add(new Claim(header.Key, header.Value));}return claims;}

这里有一个小注意事项:

如果下游服务是加权的,可以直接通过swagger添加token的方式,获取claims信息,但是接口是匿名的,那swagger是不会传递token信息的,我们可以用postman测试,一样的效果,毕竟前端Vue.js也是我们手动传递的。

关于swagger不加权就不传递token这个问题,以后我会优化下,写个扩展中间件。

查看下具体的情况:

648892be51d685343854548318f3028e.png

携带上token以后,发起请求,无论是自定义固定的参数还是Claims中的变量都传给了下游服务,并且下游的Response的Header也有了值。

好啦,网关系列的分享就先到这里了,咱们下次再见,说说注册中心集成功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291716.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HDFS HA与QJM(Quorum Journal Manager)介绍及官网内容整理

问题导读1.HDFS HA与QJM解决了什么问题&#xff1f; 2.HDFS HA与QJM区别是什么&#xff1f; 3.在HA&#xff08;两个namenode&#xff09;架构下&#xff0c;如何访问hdfs文件&#xff1f;【使用QJM构建HDFS HA架构(2.2)】本文主要介绍HDFS HA特性&#xff0c;以及如何使用QJM(…

#时间预测算法_【时间序列】时序预测竞赛之异常检测算法综述

本文将介绍在时间序列预测相关问题中常见的异常检测算法&#xff0c;可以很大程度上帮助改善最终预测效果。异常分类时间序列的异常检测问题通常表示为相对于某些标准信号或常见信号的离群点。虽然有很多的异常类型&#xff0c;但是我们只关注业务角度中最重要的类型&#xff0…

监测利器cacti服务安装

1、Cacti原理及概述1Cacti是一款使用PHP语言开发的性能与流量监测工具。监测的对象可以是linux也可以是windows也可以是路由器交换机等网络设备主要基于SNMPsimple network managerprotocol简单网络管理协议来搜集cpu占用内存使用运行进程数磁盘空间网卡流量等各种网络数据。2实…

C#中的类型转换

前几篇文章中经常说到强制类型转换&#xff0c;就是可以将派生类对象强制转换为基类对象的做法或者通过as运算符进行的转换。今天我们就来一起简单了解复习下在C#中都有哪些类型的转换。要理解转换很容易&#xff0c;日常的开发编码过程中&#xff0c;由于变量类型的不同我们可…

linux之快速过滤文本的关键字以及快速过滤目录下的关键字

1、快速过过滤文本的关键字 cat file | grep 关键字 比如Android日志文件很长&#xff0c;需要过滤Exception,就可以用这个办法&#xff0c;如下图 2、快速过滤目录下的关键字 grep -r 关键字 比如我们在linux上看目录下哪些关键字段&#xff0c;好像开发工具里面的 find usag…

hadoop使用

2019独角兽企业重金招聘Python工程师标准>>> 框架简介 Hadoop使用主/从&#xff08;Master/Slave&#xff09;架构&#xff0c;主要角色有NameNode&#xff0c;DataNode&#xff0c;secondary NameNode&#xff0c;JobTracker&#xff0c;TaskTracker组成。 其中Nam…

bigint hive java类型_详解Apache Hudi如何配置各种类型分区

1. 引入Apache Hudi支持多种分区方式数据集&#xff0c;如多级分区、单分区、时间日期分区、无分区数据集等&#xff0c;用户可根据实际需求选择合适的分区方式&#xff0c;下面来详细了解Hudi如何配置何种类型分区。2. 分区处理为说明Hudi对不同分区类型的处理&#xff0c;假定…

C#中的命名空间和程序集

前言今天这篇文章和大家一起学习下C#语言下的命名空间和程序集。在日常的编码工作中&#xff0c;我们对命名空间和程序集都不会很陌生。在创建项目文件时&#xff0c;IDE自动会为我们创建好一个大的命名空间和程序集。大多数业务代码都是在解决方案下各自的命令空间里进行编码的…

基于jQuery的ajax系列之用FormData实现页面无刷新上传

接着上一篇ajax系列之用jQuery的ajax方法向服务器发出get和post请求写&#xff0c;这篇主要写如何利用ajax和FormData实现页面无刷新的文件上传效果&#xff0c;主要用到了jQuery的ajax()方法和XMLHttpRequest Level 2的FormData接口。关于FormData&#xff0c;大家可以看MDN文…

abd shell关闭所有程序_在后台服务器上运行程序

之前总结过screen的用法&#xff0c;但还可以用nohup命令。nohup工具&#xff1a;Linux系统中有提供一个很好的不挂断地运行命令——nohup。我们使用nohup能很简单的控制使用&#xff0c;在此就简单的介绍一下nohup工具。nohup 命令nohup就是不挂起的意思( no hang up)。用途&a…

解锁JDK 12的奇妙之旅:新特性详解

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 解锁JDK 12的奇妙之旅&#xff1a;新特性详解 前言switch表达式拓展NumberFormat对复杂数字的格式化字符串支持transform、indent操作新增方法Files.mismatch(Path, Path)Teeing Collector支持unicode…

.NET6之MiniAPI(十四):跨域CORS(上)

为了说明跨请求&#xff0c;创建了两个项目&#xff0c;一个mini api&#xff0c;端口是5001&#xff0c;另一个razor page项目&#xff0c;端口是5280。5280项目会在页面用ajax的方式来请求5001&#xff0c;形成跨域请求&#xff0c;由于是本地测试&#xff0c;host都是localh…

django model filter 条件过滤,及多表连接查询、反向查询,某字段的distinct

2019独角兽企业重金招聘Python工程师标准>>> 1.多表连接查询&#xff1a;当我知道这点的时候顿时觉得django太NX了。 class A(models.Model): name models.CharField(u名称) class B(models.Model): aa models.ForeignKey(A)B.objects.filter(aa__name__c…

利用tabluea分析数据的案例_利用德温特分析Dartsip的案例检索结果

德温特创新平台(Derwent Innovation)与Darts-ip知识产权案例数据库均是科睿唯安旗下的知识产权数据库&#xff0c;虽然这两个数据库的侧重点分别在于专利信息与知识产权判例&#xff0c;但若将两者结合使用则能发挥11>2的作用&#xff0c;打通专利全生命周期。关注我们的朋友…

linux网络编程之怎么配置好unp.h文件

1、获取unp源码 下载地址:http://www.unpbook.com/src.html 然后用tar -zxvf unpv13e.tar.gz命令解压 2、进入unpv13e目录执行configure cd unpv13e ,然后执configure文件 3、打开README文件,使用make命令 打开README文件

客户端禁用Keep-Alive, 服务端开启Keep-Alive,会怎么样?

最近部署的web程序&#xff0c;服务器上出现不少time_wait的tcp连接状态&#xff0c;占用了tcp端口&#xff0c;花费几天时间排查。之前我有结论&#xff1a;HTTP keep-alive 是在应用层对TCP连接的滑动续约复用&#xff0c;如果客户端、服务器稳定续约&#xff0c;就成了名副其…

linux网络编程之一般应用采用的协议和不同套接字的地址结构以及用户进程和内核通过哪些函数传递套接字的地址结构

1、一般应用采用的协议 2、不同套接字的地址结构 3、用户进程和内核通过哪些函数传递套接字的地址结构 从进程到内核传递套接字的地址结构函数有3个 bind、connect、sendto函数 从内核到进程传递套接字的地址结构函数有4个函数 accept、recvfrom 、getsockname 、getpeername…

四则运算2测试

这是测试程序在输入任意字符时能否正常运行 1&#xff09;按程序提示正确输入 结果无错 2)当输入错误的字符&#xff0c;如字母等&#xff0c;程序出错&#xff08;错误提示无限循环&#xff09; 这一错误我经过长时间反正为解决&#xff0c;于是请教了其他同学&#xff0c;发现…

2020-11-04关于出现tomcat启动失败的一种原因

点击run on server后出现了如下所示&#xff1a; 本来是运行正常的&#xff0c;后来因为我将exp5里面所有的文件都复制了一遍&#xff0c;放到了exp5_2里面后&#xff0c;如下所示&#xff1a; 此时&#xff08;复制文件夹之前&#xff09;若tomcat已经启动&#xff0c;则不会出…

HTTP协议快速入门

一、定义 The Hypertext Transfer Protocol (HTTP) is an application protocol for distributed, collaborative, hypermedia information systems. HTTP is the foundation of data communication for the World Wide Web. Hypertext is structured text that uses logical l…