简体   繁体   English

Apache 代理后面带有嵌入式 Tomcat 的 Spring Boot

[英]Spring Boot with embedded Tomcat behind Apache proxy

We have a Spring Boot (Spring MVC) app with embedded Tomcat on a dedicated appserver behind an Apache SSL proxy.我们有一个 Spring Boot (Spring MVC) 应用程序,在 Apache SSL 代理后面的专用应用程序服务器上嵌入了 Tomcat。

The SSL port on the proxy server is 4433, forwarding to port 8080 on the appserver.代理服务器上的 SSL 端口是 4433,转发到应用服务器上的端口 8080。

So the URL to the proxy server is forwarding like:因此,代理服务器的 URL 转发如下:

https://proxyserver:4433/appname   >>forward>>   http://appserver:8080/

When running WITHOUT proxy, the first thing that happens is that在没有代理的情况下运行时,发生的第一件事是
Spring Security redirects the request, like: Spring Security 重定向请求,例如:

http://appserver:8080/   >>redirect>>   http://appserver:8080/login

to display the login form, by extending WebSecurityConfigurerAdapter with通过扩展WebSecurityConfigurerAdapter来显示登录表单

  ...
  httpSecurity.formLogin().loginPage("/login") ...
  ...

It works fine without the proxy, but WITH proxy the redirect needs to be changed,它在没有代理的情况下工作正常,但是使用代理重定向需要更改,
so Spring should instead redirect to the corresponding proxy URL, like:所以 Spring 应该重定向到相应的代理 URL,例如:

http://appserver:8080/   >>redirect>>   https://proxyserver:4433/appname/login

but no success yet.但还没有成功。

I am trying to apply this solution: 59.8 Use Tomcat behind a front-end proxy server我正在尝试应用此解决方案: 59.8 Use Tomcat behind a front-end proxy server

We have configured mod_proxy in Apache, and verified that it sends the expected headers:我们已经在 Apache 中配置了mod_proxy ,并验证它发送了预期的标头:

X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https

The application is started with parameters:应用程序以参数启动:

export ARG1='-Dserver.tomcat.protocol-header=x-forwarded-proto' 
export ARG2='-Dserver.tomcat.remote-ip-header=x-forwarded-for'
java $ARG1 $ARG2 -jar webapp.jar

Still the redirect does not work.仍然重定向不起作用。

It will keep redirecting locally, to http://appserver:8080/login which is not available to the clients.它将继续在本地重定向到客户端无法使用的http://appserver:8080/login

Is there anything else we need to do to make this scenario work?我们还需要做些什么来使这个场景起作用?


UPDATE更新

Also, I am concerned about the "/appname" part in the proxy URL.另外,我担心代理 URL 中的“/appname”部分。 On the appserver the application is rooted at "/".在应用程序服务器上,应用程序以“/”为根。 How should Spring be instructed that "/appname" should be included in all URLs sent back to the clients, when going thru the proxy?当通过代理时,应该如何指示 Spring 将“/appname”包含在发送回客户端的所有 URL 中?

I had the same problem the other day.前几天我遇到了同样的问题。 After some debugging of Spring Boot 1.3 I found the following solution.在对 Spring Boot 1.3 进行一些调试后,我找到了以下解决方案。

1. You have to setup the headers on your Apache proxy: 1.您必须在 Apache 代理上设置标头:

<VirtualHost *:443>
    ServerName www.myapp.org
    ProxyPass / http://127.0.0.1:8080/
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    ProxyPreserveHost On
    ... (SSL directives omitted for readability)
</VirtualHost>

2. You have to tell your Spring Boot app to use these headers. 2.您必须告诉您的 Spring Boot 应用程序使用这些标头。 So put the following line in your application.properties (or any other place where Spring Boots understands properties):所以把下面这行放在你的 application.properties (或任何其他 Spring Boots 理解属性的地方):

server.use-forward-headers=true

If you do these two things correctly, every redirect your application sends will not go to http://127.0.0.1:8080/[path] but automatically to https://www.myapp.com/[path]如果你正确地做这两件事,你的应用程序发送的每个重定向都不会转到http://127.0.0.1:8080/[path]而是自动转到https://www.myapp.com/[path]

Update 1. The documentation about this topic is here .更新 1.关于这个主题的文档在这里 You should read it at least to be aware of the property server.tomcat.internal-proxies which defines the range of IP-addresses for proxy servers that can be trusted.您至少应该阅读它以了解属性server.tomcat.internal-proxies ,它定义了可以信任的代理服务器的 IP 地址范围。

Update 2021 The documentation is moved to here .更新 2021文档移至此处 The Spring Boot configuration is a litte different now. Spring Boot 配置现在有点不同。

Your proxy looks fine, and so does the backend app, up to a point, but it doesn't seem to be seeing the RemoteIpValve modified request.您的代理看起来不错,后端应用程序也是如此,在某种程度上,但它似乎没有看到RemoteIpValve修改后的请求。 The default behaviour of the RemoteIpValve includes a pattern match for the proxy IP address (as a security check) and it only modifies requests that it thinks are from a valid proxy. RemoteIpValve的默认行为包括代理 IP 地址的模式匹配(作为安全检查),它只修改它认为来自有效代理的请求。 The pattern defaults in Spring Boot to a well-known set of internal IP addresses like 10.*.*.* and 192.168.*.* , so if your proxy isn't on one of those you need to explicitly configure it, eg Spring Boot 中的模式默认为一组众所周知的内部 IP 地址,如10.*.*.*192.168.*.* ,因此如果您的代理不在其中之一,则您需要明确配置它,例如

server.tomcat.internal-proxies=172\\.17\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}

(using properties file format, which means you have to double escape the backslashes). (使用属性文件格式,这意味着您必须对反斜杠进行双重转义)。

You can see the what is happening in the RemoteIpValve if you set如果您设置,您可以看到RemoteIpValve发生的事情

logging.level.org.apache.catalina.valves.RemoteIpValve=DEBUG

or set a breakpoint in it.或在其中设置断点。

A typical solution to this problem is to let the proxy handle any required rewrite.这个问题的典型解决方案是让代理处理任何需要的重写。 For example, in Apache you can use the rewrite_module and/or headers_module to correct headers.例如,在 Apache 中,您可以使用rewrite_module和/或headers_module来更正标头。 As another example, Nginx handles this and other similar cases automatically for you after configuring upstream servers.再举一个例子,Nginx 会在配置上游服务器后自动为你处理这种情况和其他类似的情况。

In response to comments:回应评论:

What are the remote_ip_header and protocol_header spring boot configuration values? remote_ip_header 和 protocol_header spring boot 配置值是什么?

Let's forget Spring Boot for a moment.让我们暂时忘记 Spring Boot。 Tomcat, the embedded servlet container, features a valve known as the RemoteIpValve. Tomcat 是嵌入式 servlet 容器,具有称为 RemoteIpValve 的阀门。 This valve is a port of the Apache remotip_module .这个阀是 Apache remotip_module 的一个端口。 The primary purpose of this valve is to treat the "useragent which initiated the request as the originating useragent" for "the purposes of authorization and logging".此阀的主要目的是将“发起请求的用户代理视为原始用户代理”以实现“授权和记录的目的”。 In order for this valve to be used it needs to be configured.为了使用该阀,需要对其进行配置。

Please find more information about this valve here .在此处找到有关此阀门的更多信息。

Spring Boot conveniently supports configuring this valve via application.properties through the server.tomcat.remote_ip_header and server.tomcat.protocol_header properties. Spring Boot 通过 server.tomcat.remote_ip_header 和 server.tomcat.protocol_header 属性通过 application.properties 方便地支持配置此阀。

I had exactly the same case using haproxy as load balancer with the below configuration, which worled for me.我有完全相同的情况,使用 haproxy 作为具有以下配置的负载均衡器,这对我来说很合适。 The only thing is the client IP is in request.getRemoteAddr() and not in "X-Forwarded-For" header唯一的问题是客户端 IP 在request.getRemoteAddr()而不是在"X-Forwarded-For"标头中

frontend www
  bind *:80
  bind *:443 ssl crt crt_path
  redirect scheme https if !{ ssl_fc }
  mode http
  default_backend servers

backend servers
  mode http
  balance roundrobin
  option forwardfor
  server S1 host1:port1 check
  server S2 host2:port2 check
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }

In application.properties:在 application.properties 中:

 server.use-forward-headers=true

There are several properties that you can configure, related to this.您可以配置几个与此相关的属性。 application.yaml example: application.yaml示例:

server:
  forward-headers-strategy: native
  tomcat:
    use-relative-redirects: true
    protocol-header: x-forwarded-proto
    remote-ip-header: x-forwarded-for

Setting server.forward-headers-strategy: native is the replacement of the deprecated server.use-forward-headers:true设置server.forward-headers-strategy: native是对已弃用的server.use-forward-headers:true的替换

Have you tried setting你有没有试过设置

  server.context-path=/appname

In Spring Boot?在 Spring Boot 中?

Try setting the Rewrite rule like: https://proxyserver:4433/appname >>forward>> http://appserver:8080/appname尝试设置重写规则,如: https://proxyserver:4433/appname >>forward>> http://appserver:8080/appname

And then set your application context to "appname" server.context-path=/appname然后将您的应用程序上下文设置为“appname” server.context-path=/appname

So locally you can run by http://appserver:8080/appname and via Reverse Proxy you access via https://proxyserver:4433/appname因此,您可以在本地通过http://appserver:8080/appname 运行并通过反向代理通过https://proxyserver:4433/appname 访问

Since I am using JBOSS, changes in standalone.xm of jboss:由于我使用的是 JBOSS,因此在 jboss 的 standalone.xm 中发生了变化:

<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>

Tomcat would have similar config, to inform Tomcat (proxy-address-forwarding="true") to respect the proxy forwarding address. Tomcat 会有类似的配置,通知 Tomcat (proxy-address-forwarding="true") 尊重代理转发地址。

server.use-forward-headers=true did not work for me, experienced a weird issue where X-Forwarded-For header is not populated to HttpServletRequest consistently. server.use-forward-headers=true对我不起作用,遇到了一个奇怪的问题,即X-Forwarded-For标头未一致地填充到HttpServletRequest

Ended up using ForwardedHeaderFilter : https://stackoverflow.com/a/51500554/986942 .最终使用ForwardedHeaderFilterhttps : //stackoverflow.com/a/51500554/986942

On top of that, make sure the load balancer (proxy) provide the following headers properly:最重要的是,确保负载均衡器(代理)正确提供以下标头:

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Spring 带有嵌入式 Tomcat 的引导在 Apache ZEA52C36203C5F99C3CE2442D531B1 后面 - Spring Boot with embedded Tomcat behind Apache SSL proxy 带有嵌入式 Tomcat 的 Spring Boot 应用程序在请求 /contextPath 时不重定向到 https 而不使用尾部斜杠 - Spring Boot application with embedded Tomcat behind reverse proxy not redirecting to https when asking for /contextPath without trailing slash 在 thymeleaf 中设置上下文名称,spring 引导部署在 apache 反向代理后面的 tomcat8 上 - Setting context name in thymeleaf with spring boot deployed on tomcat8 behind apache reverse proxy Spring Boot - 嵌入式 Tomcat - Spring boot - Embedded Tomcat Spring pageContext.request.contextPath 与 Apache 后面的 Tomcat 作为反向代理 - Spring pageContext.request.contextPath with Tomcat behind Apache as reverse proxy EnableLoadTimeWeaving Spring Boot嵌入式Tomcat - EnableLoadTimeWeaving Spring Boot Embedded Tomcat Spring Boot(嵌入式Tomcat无法启动) - Spring Boot (Embedded Tomcat Not Starting) Spring Boot 嵌入式 Tomcat 性能 - Spring Boot Embedded Tomcat Performance Spring启动嵌入式tomcat日志 - Spring boot embedded tomcat logs 在 spring-boot 中的嵌入式 apache tomcat 中配置“tomcat-server.xml”文件 - Configuring 'tomcat-server.xml' file inside of embedded apache tomcat in spring-boot
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM