Wir haben eine Spring-Boot/Spring-MVC-App mit eingebettetem Tomcat auf einem dedizierten App-Server hinter einem Apache-SSL-Proxy.
Der SSL-Port auf dem Proxyserver ist 4433 und wird an Port 8080 des Anwendungsservers weitergeleitet.
Die URL zum Proxy-Server leitet also weiter:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
Wenn OHNE Proxy ausgeführt wird, geschieht dies als erstes
spring-security leitet die Anfrage um, wie zum Beispiel:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
um das Anmeldeformular anzuzeigen, erweitern Sie WebSecurityConfigurerAdapter
um
...
httpSecurity.formLogin().loginPage("/login") ...
...
Ohne Proxy funktioniert es einwandfrei .__, aber MIT Proxy muss die Weiterleitung geändert werden Spring sollte stattdessen auf die entsprechende Proxy-URL umleiten, z.
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
aber noch kein Erfolg.
Ich versuche diese Lösung anzuwenden:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-Tomcat-behind-a-proxy-server (59.8 Tomcat hinter einer Front verwenden- Proxy-Server beenden)
Wir haben mod_proxy in Apache konfiguriert und überprüft, dass die erwarteten Header gesendet werden:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
Die Anwendung wird mit Parametern gestartet:
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
Die Weiterleitung funktioniert immer noch nicht.
Es wird weiterhin lokal weitergeleitet zu http://appserver:8080/login
, das für die Clients nicht verfügbar ist.
Gibt es noch etwas, was wir tun müssen, damit dieses Szenario funktioniert?
EDIT: Ich mache mir auch Sorgen um den Teil "/ appname" in der Proxy-URL. Auf dem Anwendungsserver befindet sich die Anwendung unter "/". Wie sollte spring darüber informiert werden, dass "/ appname" in alle URLs eingeschlossen werden muss, die an die Clients zurückgesendet werden, wenn sie über den Proxy gehen?
Ich hatte das gleiche Problem am anderen Tag. Nach einigem Debuggen von Spring Boot 1.3 habe ich folgende Lösung gefunden.
1. Sie müssen die Header auf Ihrem Apache-Proxy einrichten:
<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. Sie müssen Ihre Spring Boot-App anweisen, diese Header zu verwenden. Fügen Sie die folgende Zeile in Ihre application.properties ein (oder an einen anderen Ort, an dem Spring Boots die Eigenschaften versteht):
server.use-forward-headers=true
Wenn Sie diese beiden Dinge richtig ausführen, wird jede Weiterleitung, die Ihre Anwendung sendet, nicht unter http://127.0.0.1:8080/[path] ablaufen, jedoch automatisch an https: //www.myapp .com/[Pfad]
Update 1. Die Dokumentation zu diesem Thema ist hier . Sie sollten es zumindest lesen, um sich der Eigenschaft server.Tomcat.internal-proxies
bewusst zu sein, die den Bereich der IP-Adressen für Proxyserver definiert, der vertrauenswürdig sein kann.
Ihr Proxy sieht gut aus, und auch die Backend-App tut dies bis zu einem gewissen Punkt, aber die RemoteIpValve
-geänderte Anforderung scheint nicht zu erscheinen. Das Standardverhalten von RemoteIpValve
enthält eine Musterübereinstimmung für die Proxy-IP-Adresse (als Sicherheitsüberprüfung) und modifiziert nur Anforderungen, die ihrer Meinung nach von einem gültigen Proxy stammen. Das Muster ist in Spring Boot standardmäßig auf einen bekannten Satz interner IP-Adressen wie 10.*.*.*
und 192.168.*.*
festgelegt. Wenn sich Ihr Proxy nicht auf einem dieser Adressen befindet, müssen Sie ihn explizit konfigurieren, z.
server.Tomcat.internal-proxies=172\\.17\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}
(Bei Verwendung des Eigenschaftendateiformats müssen Sie die umgekehrten Schrägstriche doppelt kennzeichnen).
Sie können in der RemoteIpValve
sehen, was passiert, wenn Sie festlegen
logging.level.org.Apache.catalina.valves.RemoteIpValve=DEBUG
oder legen Sie einen Haltepunkt fest.
Eine typische Lösung für dieses Problem besteht darin, dass der Proxy das erforderliche Neuschreiben durchführen muss. In Apache können Sie beispielsweise das rewrite_module und/oder headers_module verwenden, um die Header zu korrigieren. In einem anderen Beispiel behandelt Nginx diese und andere ähnliche Fälle automatisch nach der Konfiguration der Upstream-Server.
Als Antwort auf Kommentare:
Wie lauten die Konfigurationswerte für den Spring-Boot remote_ip_header und protocol_header?
Vergessen wir Spring Boot für einen Moment. Tomcat, der eingebettete Servlet-Container, verfügt über ein als RemoteIpValve bekanntes Ventil. Dieses Ventil ist ein Port des Apache remotip_module . Der Hauptzweck dieses Ventils besteht darin, den "Benutzeragenten, der die Anforderung initiiert hat", als den ursprünglichen Benutzeragenten "zum Zwecke der Autorisierung und Protokollierung" zu behandeln. Damit dieses Ventil verwendet werden kann, muss es konfiguriert werden.
Weitere Informationen zu diesem Ventil hier .
Spring Boot unterstützt die Konfiguration dieses Ventils bequem über application.properties über die Eigenschaften server.Tomcat.remote_ip_header und server.Tomcat.protocol_header.
Ich hatte genau den gleichen Fall bei der Verwendung von Haproxy als Load Balancer mit der folgenden Konfiguration, was für mich problematisch war. Die Client-IP befindet sich nur in request.getRemoteAddr()
und nicht in "X-Forwarded-For"
-Header
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:
server.use-forward-headers=true
Stellen Sie die Rewrite-Regel wie folgt ein: https: // proxyserver: 4433/appname >> forward >> http: // appserver: 8080/appname
Setzen Sie dann Ihren Anwendungskontext auf "Anwendungsname" server.context-path =/appname
Sie können also lokal von http: // appserver: 8080/appname laufen, und über Reverse Proxy können Sie über https: // proxyserver: 4433/appname zugreifen.
Da ich JBOSS verwende, ändert sich in Standalone.xm von JBoss:
<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
Tomcat hätte eine ähnliche Konfiguration, um Tomcat mitzuteilen (Proxy-Address-Forwarding = "true"), die Proxy-Weiterleitungsadresse zu respektieren.
Hast du das Einstellen versucht?
server.context-path=/appname
Im Frühling Boot?