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块,通过调用ProxyRequestHelper的addIgnoredHeaders方法来添加需要忽略的信息到请求上下文中,供后续ROUTE阶段的过滤器使用。这里的if/else块分别用来处理全局设置的敏感头信息和指定路由设置的敏感头信息。而全局的敏感头信息定义于ZuulProperties中:
@Data @ConfigurationProperties("zuul") public class ZuulProperties{ private Set<String> sensitiveHeaders = new LinkedHashSet<>( Arrays.asList("Cookie", "Set-Cookie", "Authorization")); ... }所以解决该问题的思路也很简单,源码库我们只需要通过设置sensitiveHeaders即可,设置方法分为两种:
1. 全局设置:
zuul.sensitive-headers=2. 指定路由设置:
zuul.routes..sensitive-headers= zuul.routes..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过滤器的源码来详细更多实现细节。
【本文为专栏作者“翟永超”的原创稿件,转载请通过联系作者获取授权】
戳这里,看该作者更多好文
相关文章
探讨电脑插着U盘启动错误的原因及解决方法(分析电脑插着U盘启动错误的情况,掌握解决技巧)
摘要:在使用电脑过程中,有时候我们会遇到插着U盘启动出现错误的情况。这种问题可能会导致电脑无法正常启动,给我们的工作和生活带来不便。本文将从各个方面探讨电脑插着U盘启动错误的原因,并提供...2025-11-05- 摘要:广济桃花,位于中国江苏省扬州市广陵区,被誉为中国最美的桃花园之一。每年春天,数百亩桃花竞相绽放,绚丽多彩,吸引了众多游客前来观赏和拍照。本文将以广济桃花为主题,介绍其景点特色和与桃...2025-11-05
- 摘要:作为智能手机市场中的一员,天宏X6以其强大的性能和丰富的功能吸引了众多消费者的关注。本文将对天宏X6进行全面评测,包括外观设计、性能指标、拍照效果、用户体验等方面的内容,同时分享一...2025-11-05
- 摘要:人类的繁殖是我们生存和延续物种的基本需求,它经历了漫长的进化历程,同时也受到科技的影响。本文将探讨人类繁殖的演化过程以及未来的发展方向。一:从古代到现代——人类繁殖的历史进...2025-11-05
电脑安装ADM插线教程(一步步教你安装ADM插线,畅享高速网络)
摘要:在如今数字化的时代,快速、稳定的网络连接已经成为了人们日常生活和工作中不可或缺的一部分。ADM插线可以帮助我们快速连接到网络,提供更稳定、更高速的网络体验。本文将为大家详细介绍如何...2025-11-05以舒华跑步机怎么样?-一款高品质的运动设备(舒适稳定、多功能智能的健身伙伴)
摘要:在现代快节奏的生活中,如何保持身体健康成为越来越多人关注的话题。而有氧运动是保持健康的重要方式之一,而跑步作为最常见的有氧运动方式,备受人们的喜爱。本文将以舒华跑步机为例,来探讨其...2025-11-05

最新评论