回答问题

背景

我最近将我的 Spring 应用程序迁移到 Spring Boot(带有嵌入式 Tomcat),我目前正在将它迁移到 Kubernetes。作为迁移到 Kubernetes 的一部分,我将 Apache 配置分离到它自己的服务中,并在 Kubernetes 中部署以充当我的 Spring Boot 应用程序的代理。

我当前的设置是带有 LoadBalancer 服务的 Apache,它接受来自世界各地的请求。这会接收这些请求并将它们转发到我的 Spring Boot 应用程序,该应用程序具有 ClusterIP 服务。

另外需要注意的是:我的 Apache 将所有 http 重定向到 https。

问题

每当我的 Spring Boot 应用程序向客户端返回重定向时,响应中的位置标头是 http 而不是 https(只有通过 https 发出的请求才会通过 Apache 代理到达我的应用程序)。

例子:

未登录用户前往:

https://example.com/admin

如果未通过身份验证,则管理页面会将用户重定向到登录页面。这应该是一个重定向到:

https://example.com/login

但是,我的应用程序将用户重定向到:

http://example.com/login

然后用户被 Apache 再次重定向到:

https://example.com/login

我试过的

我检查了我的日志,以确保我的应用收到的请求包含X-Forwarded-Proto: https标头,据我了解,这应该使重定向响应 https 中的位置标头。

正如几篇 Stack Overflow 帖子中提到的,我尝试将server.use-forward-headers=true添加到我的application.properties文件中,但这没有任何作用。我也尝试用它添加server.tomcat.protocol-header=X-Forwarded-Proto,但这也没有做任何事情(从我读到的,无论如何都是默认值)。

其他说明

  • 我的集群的networkCIDR包含在 Tomcat 的RemoteIPValve内部代理列表中

  • X-Forwarded-For似乎也没有影响,所以我认为问题在于所有转发标题

Answers

我想到了。我的错误是假设networkCIDRrequest.getRemoteAddr()返回的IP地址,而实际上它是我的k8s内部集群IP。这是有道理的,因为请求来自同样位于集群内部的 Apache。内部集群 IP 不在内部代理列表中,因此RemoteIPValve没有使用转发头。

通过使用RemoteIpValve中指定的默认值和我的内部集群 IP 将server.tomcat.internal-proxies属性添加到我的application.properties中,一切正常。

见https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-customize-tomcat-behind-a-proxy-server

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐