转发标头在Spring Boot + Kubernetes中不起作用

时间:2017-10-11 23:09:07

标签: java apache tomcat spring-boot kubernetes

背景

我最近将我的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似乎也没有影响,所以我认为问题在于所有转发标题

1 个答案:

答案 0 :(得分:3)

我明白了。我的错误是假设networkCIDRrequest.getRemoteAddr()返回的IP地址,而它实际上是我的k8s内部集群IP。这是有意义的,因为请求来自Apache,它也在集群内部。内部群集IP不在内部代理列表中,因此RemoteIPValve未使用转发头。

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

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