[英]Spring Boot with embedded Tomcat behind Apache SSL proxy
[英]Spring Boot with embedded Tomcat behind Apache proxy
我們有一個 Spring Boot (Spring MVC) 應用程序,在 Apache SSL 代理后面的專用應用程序服務器上嵌入了 Tomcat。
代理服務器上的 SSL 端口是 4433,轉發到應用服務器上的端口 8080。
因此,代理服務器的 URL 轉發如下:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
在沒有代理的情況下運行時,發生的第一件事是
Spring Security 重定向請求,例如:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
通過擴展WebSecurityConfigurerAdapter
來顯示登錄表單
...
httpSecurity.formLogin().loginPage("/login") ...
...
它在沒有代理的情況下工作正常,但是使用代理重定向需要更改,
所以 Spring 應該重定向到相應的代理 URL,例如:
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
但還沒有成功。
我正在嘗試應用此解決方案: 59.8 Use Tomcat behind a front-end proxy server
我們已經在 Apache 中配置了mod_proxy ,並驗證它發送了預期的標頭:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
應用程序以參數啟動:
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
仍然重定向不起作用。
它將繼續在本地重定向到客戶端無法使用的http://appserver:8080/login
。
我們還需要做些什么來使這個場景起作用?
另外,我擔心代理 URL 中的“/appname”部分。 在應用程序服務器上,應用程序以“/”為根。 當通過代理時,應該如何指示 Spring 將“/appname”包含在發送回客戶端的所有 URL 中?
前幾天我遇到了同樣的問題。 在對 Spring Boot 1.3 進行一些調試后,我找到了以下解決方案。
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.您必須告訴您的 Spring Boot 應用程序使用這些標頭。 所以把下面這行放在你的 application.properties (或任何其他 Spring Boots 理解屬性的地方):
server.use-forward-headers=true
如果你正確地做這兩件事,你的應用程序發送的每個重定向都不會轉到http://127.0.0.1:8080/[path]而是自動轉到https://www.myapp.com/[path]
更新 1.關於這個主題的文檔在這里。 您至少應該閱讀它以了解屬性server.tomcat.internal-proxies
,它定義了可以信任的代理服務器的 IP 地址范圍。
更新 2021文檔移至此處。 Spring Boot 配置現在有點不同。
您的代理看起來不錯,后端應用程序也是如此,在某種程度上,但它似乎沒有看到RemoteIpValve
修改后的請求。 RemoteIpValve
的默認行為包括代理 IP 地址的模式匹配(作為安全檢查),它只修改它認為來自有效代理的請求。 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}
(使用屬性文件格式,這意味着您必須對反斜杠進行雙重轉義)。
如果您設置,您可以看到RemoteIpValve
發生的事情
logging.level.org.apache.catalina.valves.RemoteIpValve=DEBUG
或在其中設置斷點。
這個問題的典型解決方案是讓代理處理任何需要的重寫。 例如,在 Apache 中,您可以使用rewrite_module和/或headers_module來更正標頭。 再舉一個例子,Nginx 會在配置上游服務器后自動為你處理這種情況和其他類似的情況。
回應評論:
remote_ip_header 和 protocol_header spring boot 配置值是什么?
讓我們暫時忘記 Spring Boot。 Tomcat 是嵌入式 servlet 容器,具有稱為 RemoteIpValve 的閥門。 這個閥是 Apache remotip_module 的一個端口。 此閥的主要目的是將“發起請求的用戶代理視為原始用戶代理”以實現“授權和記錄的目的”。 為了使用該閥,需要對其進行配置。
請在此處找到有關此閥門的更多信息。
Spring Boot 通過 server.tomcat.remote_ip_header 和 server.tomcat.protocol_header 屬性通過 application.properties 方便地支持配置此閥。
我有完全相同的情況,使用 haproxy 作為具有以下配置的負載均衡器,這對我來說很合適。 唯一的問題是客戶端 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 }
在 application.properties 中:
server.use-forward-headers=true
您可以配置幾個與此相關的屬性。 application.yaml
示例:
server:
forward-headers-strategy: native
tomcat:
use-relative-redirects: true
protocol-header: x-forwarded-proto
remote-ip-header: x-forwarded-for
設置server.forward-headers-strategy: native
是對已棄用的server.use-forward-headers:true
的替換
你有沒有試過設置
server.context-path=/appname
在 Spring Boot 中?
嘗試設置重寫規則,如: https://proxyserver:4433/appname >>forward>> http://appserver:8080/appname
然后將您的應用程序上下文設置為“appname” server.context-path=/appname
因此,您可以在本地通過http://appserver:8080/appname 運行並通過反向代理通過https://proxyserver:4433/appname 訪問
由於我使用的是 JBOSS,因此在 jboss 的 standalone.xm 中發生了變化:
<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
Tomcat 會有類似的配置,通知 Tomcat (proxy-address-forwarding="true") 尊重代理轉發地址。
server.use-forward-headers=true
對我不起作用,遇到了一個奇怪的問題,即X-Forwarded-For
標頭未一致地填充到HttpServletRequest
。
最終使用ForwardedHeaderFilter
: https : //stackoverflow.com/a/51500554/986942 。
最重要的是,確保負載均衡器(代理)正確提供以下標頭:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.