Spring Cloud实战小贴士:Zuul处理Cookie和重定向

由于我们在之前所有的入门教程中,对于HTTP请求都采用了简单的接口实现。而实际使用过程中,我们的HTTP请求要复杂的多,比如当我们将Spring Cloud Zuul作为API网关接入网站类应用时,往往都会碰到下面这两个非常常见的问题:

  • 会话无法保持
  • 重定向后的HOST错误

本文将帮助大家分析问题原因并给出解决这两个常见问题的方法。

会话保持问题

通过跟踪一个HTTP请求经过Zuul到具体服务,再到返回结果的全过程。我们很容易就能发现,在传递的过程中,HTTP请求头信息中的Cookie和Authorization都没有被正确地传递给具体服务,所以最终导致会话状态没有得到保持的现象。

那么这些信息是在哪里丢失的呢?我们从Zuul进行路由转发的过滤器作为起点,来一探究竟。下面是RibbonRoutingFilter过滤器的实现片段:

public class RibbonRoutingFilter extends ZuulFilter {
...
protected ProxyRequestHelper helper;

@Override
public Object run() {
RequestContext context = RequestContext.getCurrentContext();
this.helper.addIgnoredHeaders();
try {
RibbonCommandContext commandContext = buildCommandContext(context);
ClientHttpResponse response = forward(commandContext);
setResponse(response);
return response;
}
...
return null;
}

protected RibbonCommandContext buildCommandContext(RequestContext context) {
HttpServletRequest request = context.getRequest();

MultiValueMap<String, String> headers = this.helper
.buildZuulRequestHeaders(request);
MultiValueMap<String, String> params = this.helper
.buildZuulRequestQueryParams(request);
...
}
}

这里有三个重要元素:

  • 过滤器的核心逻辑run函数实现,其中调用了内部函数buildCommandContext来构建上下文内容
  • buildCommandContext中调用了helper对象的buildZuulRequestHeaders方法来处理请求头信息
  • helper对象是ProxyRequestHelper类的实例

接下来我们再看看ProxyRequestHelper的实现:

public class ProxyRequestHelper {

public MultiValueMap<String, String> buildZuulRequestHeaders(
HttpServletRequest request) {
RequestContext context = RequestContext.getCurrentContext();
MultiValueMap<String, String> headers = new HttpHeaders();
Enumeration<String> headerNames = request.getHeaderNames();
if (headerNames != null) {
while (headerNames.hasMoreElements()) {
String name = headerNames.nextElement();
if (isIncludedHeader(name)) {
Enumeration<String> values = request.getHeaders(name);
while (values.hasMoreElements()) {
String value = values.nextElement();
headers.add(name, value);
}
}
}
}
Map<String, String> zuulRequestHeaders = context.getZuulRequestHeaders();
for (String header : zuulRequestHeaders.keySet()) {
headers.set(header, zuulRequestHeaders.get(header));
}
headers.set(HttpHeaders.ACCEPT_ENCODING, "gzip");
return headers;
}

public boolean isIncludedHeader(String headerName) {
String name = headerName.toLowerCase();
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey(IGNORED_HEADERS)) {
Object object = ctx.get(IGNORED_HEADERS);
if (object instanceof Collection && ((Collection<?>) object).contains(name)) {
return false;
}
}
...
}
}

从上述源码中,我们可以看到构建头信息的方法buildZuulRequestHeaders通过isIncludedHeader函数来判断当前请求的各个头信息是否在忽略的头信息清单中,如果是的话就不组织到此次转发的请求中去。那么这些需要忽略的头信息是在哪里初始化的呢?在PRE阶段的PreDecorationFilter过滤器中,我们可以找到答案:

public class PreDecorationFilter extends ZuulFilter {
...
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
final String requestURI = this.urlPathHelper.getPathWithinApplication(ctx.getRequest());
Route route = this.routeLocator.getMatchingRoute(requestURI);
if (route != null) {
String location = route.getLocation();
if (location != null) {
ctx.put("requestURI", route.getPath());
ctx.put("proxy", route.getId());
// 处理忽略头信息的部分
if (!route.isCustomSensitiveHeaders()) {
this.proxyRequestHelper.addIgnoredHeaders(
this.properties.getSensitiveHeaders()
.toArray(new String[0]));
} else {
this.proxyRequestHelper.addIgnoredHeaders(
route.getSensitiveHeaders()
.toArray(new String[0]));
}
...
}

从上述源码中,我们可以看到有一段if/else块,通过调用ProxyRequestHelperaddIgnoredHeaders方法来添加需要忽略的信息到请求上下文中,供后续ROUTE阶段的过滤器使用。这里的if/else块分别用来处理全局设置的敏感头信息和指定路由设置的敏感头信息。而全局的敏感头信息定义于ZuulProperties中:

@Data
@ConfigurationProperties("zuul")
public class ZuulProperties {
private Set<String> sensitiveHeaders = new LinkedHashSet<>(
Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
...
}

所以解决该问题的思路也很简单,我们只需要通过设置sensitiveHeaders即可,设置方法分为两种:

  • 全局设置:
    • zuul.sensitive-headers=
  • 指定路由设置:
    • zuul.routes.<routeName>.sensitive-headers=
    • zuul.routes.<routeName>.custom-sensitive-headers=true

重定向问题

在使用Spring Cloud Zuul对接Web网站的时候,处理完了会话控制问题之后。往往我们还会碰到如下图所示的问题,我们在浏览器中通过Zuul发起了登录请求,该请求会被路由到某WebSite服务,该服务在完成了登录处理之后,会进行重定向到某个主页或欢迎页面。此时,仔细的开发者会发现,在登录完成之后,我们浏览器中URL的HOST部分发生的改变,该地址变成了具体WebSite服务的地址了。这就是在这一节,我们将分析和解决的重定向问题!

出现该问题的根源是Spring Cloud Zuul没有正确的处理HTTP请求头信息中的Host导致。在Brixton版本中,Spring Cloud Zuul的PreDecorationFilter过滤器实现时完全没有考虑这一问题,它更多的定位于REST API的网关。所以如果要在Brixton版本中增加这一特性就相对较为复杂,不过好在Camden版本之后,Spring Cloud Netflix 1.2.x版本的Zuul增强了该功能,我们只需要通过配置属性zuul.add-host-header=true就能让原本有问题的重定向操作得到正确的处理。关于更多Host头信息的处理,读者可以参考本文之前的分析思路,可以通过查看PreDecorationFilter过滤器的源码来详细更多实现细节。


相关阅读

  • 《Spring Cloud源码分析(四)Zuul:核心过滤器》
  • 《Spring Cloud实战小贴士:Zuul统一异常处理(一)》
  • 《Spring Cloud实战小贴士:Zuul统一异常处理(二)》
  • 《Spring Cloud构建微服务架构(五)服务网关》

money.jpg

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

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

相关文章

论文浅尝 | Language Models (Mostly) Know What They Know

笔记整理&#xff1a;程思源、梁孝转&#xff0c;浙江大学在读硕士&#xff0c;研究方向为知识图谱的表示学习&#xff0c;自然语言处理&#xff0c;预训练对于一个语言模型&#xff0c;我们最终希望得到一个“诚实”的人工智能系统&#xff0c;即语言模型需要准确并且忠实地评…

百度AI技术盛宴来了!大咖齐聚解读CV/NLP/跨模态大模型技术!

随着人工智能步入工业大生产阶段&#xff0c;AI大模型正在加速走出实验室&#xff0c;在全球范围内逐步实现产业落地应用的突破。自2020年至今&#xff0c;越来越多的科技巨头和科研机构参与其中。去年12月&#xff0c;百度发布了全球首个知识增强千亿级大模型——鹏城-百度文心…

Spring Cloud实战小贴士:健康检查

今天在博客的交流区收到一条不错的问题&#xff0c;拿出来给大家分享一下。具体问题如下&#xff1a; 因为项目里面用到了redis集群&#xff0c;但并不是用spring boot的配置方式&#xff0c;启动后项目健康检查老是检查redis的时候状态为down&#xff0c;导致注册到eureka后项…

恕我直言,你的模型可能并没看懂 prompt 在说啥

本文转载自公众号“夕小瑶的卖萌屋”&#xff0c;专业带逛互联网算法圈的神操作 -----》我是传送门 关注后&#xff0c;回复以下口令&#xff1a; 回复【789】 &#xff1a;领取深度学习全栈手册&#xff08;含NLP、CV海量综述、必刷论文解读&#xff09; 回复【入群】&#xf…

开源开放 | 区域供冷供热系统及空调系统知识图谱

OpenKG地址&#xff1a;http://openkg.cn/dataset/less开放许可协议&#xff1a;CC BY-SA 4.0 &#xff08;署名相似共享&#xff09;贡献者&#xff1a;浙江大学&#xff08;赵阳&#xff0c;李婷婷&#xff0c;章超波&#xff09;1、背景区域供冷供热系统及空调系统领域涉及知…

LeetCode 1334. 阈值距离内邻居最少的城市(最短路径Dijkstra)

1. 题目 有 n 个城市&#xff0c;按从 0 到 n-1 编号。给你一个边数组 edges&#xff0c;其中 edges[i] [fromi, toi, weighti] 代表 fromi 和 toi 两个城市之间的双向加权边&#xff0c;距离阈值是一个整数 distanceThreshold。 返回能通过某些路径到达其他城市数目最少、且…

五个同事想计算他们的平均工资,但公司不让吐露薪资,如何实现?

源 | Xpecya知乎大家好我是卖萌酱。昨天在知乎上刷到一个很有意思的问题&#xff1a;“五个同事决定计算他们的平均工资&#xff0c;在大家互相不告诉薪水的情况下&#xff0c;如何才能做到这一点&#xff1f;”。确实互联网公司是不让员工讨论薪资的&#xff0c;但通过一些神操…

基于Consul的分布式信号量实现

本文将继续讨论基于Consul的分布式锁实现。信号量是我们在实现并发控制时会经常使用的手段&#xff0c;主要用来限制同时并发线程或进程的数量&#xff0c;比如&#xff1a;Zuul默认情况下就使用信号量来限制每个路由的并发数&#xff0c;以实现不同路由间的资源隔离。 信号量(…

图谱实战 | 图视角下的信息抽取技术研究

导读&#xff1a;本次分享题目为《图视角下的信息抽取技术研究》&#xff0c;主要介绍&#xff1a;研究背景和意义国内外研究现状研究目标与内容主要成果与创新之处完成项目及发表论文情况分享嘉宾&#xff5c;郁博文博士 达摩院 算法专家编辑整理&#xff5c;王露出品平台&…

LeetCode 1335. 工作计划的最低难度(DP)

1. 题目 你需要制定一份 d 天的工作计划表。工作之间存在依赖&#xff0c;要想执行第 i 项工作&#xff0c;你必须完成全部 j 项工作&#xff08; 0 < j < i&#xff09;。 你每天 至少 需要完成一项任务。工作计划的总难度是这 d 天每一天的难度之和&#xff0c;而一天…

CCKS-面向数字商务的知识图谱比赛重磅上线,奖金等你来拿!

​CCKS 2022面向数字商务的知识图谱评测赛题介绍阿里巴巴商品数据规模庞大&#xff0c;商品知识图谱为海量异构的商品数据的组织、管理和利用提供了有效的方式。商品数据模态丰富&#xff0c;动态性高&#xff0c;数据存在噪声&#xff0c;这些都对商品的认知和理解带来了巨大挑…

基于Consul的分布式锁实现

我们在构建分布式系统的时候&#xff0c;经常需要控制对共享资源的互斥访问。这个时候我们就涉及到分布式锁&#xff08;也称为全局锁&#xff09;的实现&#xff0c;基于目前的各种工具&#xff0c;我们已经有了大量的实现方式&#xff0c;比如&#xff1a;基于Redis的实现、基…

LeetCode 1289. 下降路径最小和 II(DP)

1. 题目 给你一个整数方阵 arr &#xff0c;定义「非零偏移下降路径」为&#xff1a;从 arr 数组中的每一行选择一个数字&#xff0c;且按顺序选出来的数字中&#xff0c;相邻数字不在原数组的同一列。 请你返回非零偏移下降路径数字和的最小值。 示例 1&#xff1a; 输入&a…

警惕“不续签劳动合同”式裁员

文 | 是小酒呀源 | 知乎正文内容来源于作者 是小酒呀知乎&#xff0c;原文链接&#xff1a;https://zhuanlan.zhihu.com/p/499838511没想到裁员还有不续约这招&#xff1f;&#xff01;&#xff01;3月14日一大早&#xff0c;leader叫我去会议室&#xff0c;进入会议室后&#…

图谱实战 | OPPO自研大规模知识图谱及其在小布助手中的应用

分享嘉宾&#xff1a;李向林 OPPO编辑整理&#xff1a;吴祺尧 加州大学圣地亚哥分校出品平台&#xff1a;DataFunTalk导读&#xff1a;OPPO知识图谱是OPPO数智工程系统小布助手团队主导、多团队协作建设的自研大规模通用知识图谱&#xff0c;目前已达到数亿实体和数十亿三元组的…

LeetCode 1284. 转化为全零矩阵的最少反转次数(BFS 矩阵状态编码解码)

1. 题目 给你一个 m x n 的二进制矩阵 mat。 每一步&#xff0c;你可以选择一个单元格并将它反转&#xff08;反转表示 0 变 1 &#xff0c;1 变 0 &#xff09;。如果存在和它相邻的单元格&#xff0c;那么这些相邻的单元格也会被反转。&#xff08;注&#xff1a;相邻的两个…

Netflix Zuul与Nginx的性能对比

这是一篇翻译&#xff0c;关于大家经常质疑的一个问题&#xff1a;API网关Zuul的性能。原文&#xff1a;NETFLIX ZUUL VS NGINX PERFORMANCE作者&#xff1a;STANISLAV MIKLIK 如今你可以听到很多关于“微服务”的信息。Spring Boot是一个用来构建单个微服务应用的理想选择&…

LeetCode 773. 滑动谜题(BFS 地图状态转换的最短距离)

1. 题目 在一个 2 x 3 的板上&#xff08;board&#xff09;有 5 块砖瓦&#xff0c;用数字 1~5 来表示, 以及一块空缺用 0 来表示. 一次移动定义为选择 0 与一个相邻的数字&#xff08;上下左右&#xff09;进行交换. 最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开…

Spring Cloud实战小贴士:随机端口

太久没有更新&#xff0c;一时不知道该从哪儿开始&#xff0c;索性就从一个小技巧开始吧。 在之前的《Spring Cloud构建微服务架构》系列博文中&#xff0c;我们经常会需要启动多个实例的情况来测试注册中心、配置中心等基础设施的高可用&#xff0c;也会用来测试客户端负载均衡…

图谱实战 | 基于金融场景的事理图谱构建与应用

分享嘉宾&#xff1a;肖楠 京东科技 算法专家编辑整理&#xff1a;付村 云融创新出品平台&#xff1a;DataFunTalk导读&#xff1a;今天分享京东科技近期在事理图谱构建和应用方面的研究成果&#xff0c;主要分为以下五个部分&#xff1a;京东科技图谱简介金融事理图谱构建因果…