Nous avons une application spring-boot/spring-mvc avec Tomcat intégré sur un serveur d'applications dédié derrière un proxy SSL Apache.
Le port SSL sur le serveur proxy est 4433 et est transféré sur le port 8080 du serveur d'applications.
Donc, l'URL du serveur proxy transfère comme ceci:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
SANS proxy, la première chose à faire est que
spring-security redirige la demande, comme suit:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
pour afficher le formulaire de connexion, en étendant WebSecurityConfigurerAdapter
avec
...
httpSecurity.formLogin().loginPage("/login") ...
...
Cela fonctionne très bien sans proxy, Mais avec proxy, la redirection doit être modifiée, Donc Spring devrait plutôt rediriger vers l'URL du proxy correspondante, comme par exemple:
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
mais pas encore de succès.
J'essaie d'appliquer cette solution:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-Tomcat-behind-a-proxy-server (59.8 Utilisez Tomcat derrière un front- serveur proxy final)
Nous avons configuré mod_proxy dans Apache et vérifié qu'il envoie les en-têtes prévus:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
L'application est démarrée avec les paramètres:
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
La redirection ne fonctionne toujours pas.
Il continuera à rediriger localement, vers http://appserver:8080/login
qui n'est pas disponible pour les clients.
Y a-t-il autre chose que nous devons faire pour que ce scénario fonctionne?
EDIT: la partie "/ appname" de l'URL du proxy m'inquiète également. Sur le serveur d'applications, l'application est rootée à "/". Comment faut-il indiquer à spring que "/ appname" doit être inclus dans toutes les URL renvoyées aux clients lors du passage par le proxy?
J'ai eu le même problème l'autre jour. Après un débogage de Spring Boot 1.3, j'ai trouvé la solution suivante.
1. Vous devez configurer les en-têtes sur votre proxy 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. Vous devez indiquer à votre application Spring Boot d'utiliser ces en-têtes. Mettez donc la ligne suivante dans votre application.properties (ou tout autre endroit où Spring Boots comprend les propriétés):
server.use-forward-headers=true
Si vous faites ces deux choses correctement, chaque redirection envoyée par votre application sera pas dans http://127.0.0.1:8080/[path] mais automatiquement vers https: //www.myapp .com/[chemin]
Mise à jour 1. La documentation sur ce sujet est ici . Vous devriez le lire au moins pour connaître la propriété server.Tomcat.internal-proxies
qui définit la plage d'adresses IP des serveurs proxy pouvant être approuvés.
Votre proxy semble bien, tout comme l’application dorsale, jusqu’à un certain point, mais elle ne semble pas voir la demande modifiée RemoteIpValve
. Le comportement par défaut de RemoteIpValve
inclut une correspondance de modèle pour l'adresse IP du proxy (en tant que contrôle de sécurité) et il ne modifie que les demandes qu'il pense émaner d'un proxy valide. Dans Spring Boot, le modèle utilise par défaut un ensemble bien connu d’adresses IP internes telles que 10.*.*.*
et 192.168.*.*
. Par conséquent, si votre proxy ne figure pas sur l’une d’entre elles, vous devez le configurer explicitement, par exemple.
server.Tomcat.internal-proxies=172\\.17\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}
(en utilisant le format de fichier de propriétés, ce qui signifie que vous devez double échapper les barres obliques inverses).
Vous pouvez voir ce qui se passe dans la RemoteIpValve
si vous définissez
logging.level.org.Apache.catalina.valves.RemoteIpValve=DEBUG
ou définir un point d'arrêt en elle.
Une solution typique à ce problème consiste à laisser le proxy gérer toute réécriture requise. Par exemple, dans Apache, vous pouvez utiliser rewrite_module et/ou headers_module pour corriger les en-têtes. Autre exemple, Nginx gère automatiquement ce cas et d’autres cas similaires après la configuration des serveurs en amont.
En réponse aux commentaires:
Quelles sont les valeurs de configuration de démarrage à ressort remote_ip_header et protocol_header?
Oublions Spring Boot pour un moment. Tomcat, le conteneur de servlets intégré, comporte une vanne appelée RemoteIpValve. Cette valve est un port de Apache remotip_module . L'objectif principal de cette vanne est de traiter "l'utilisateur qui a initié la demande en tant qu'agent d'utilisateur d'origine" aux "fins de l'autorisation et de la journalisation". Pour que cette vanne puisse être utilisée, elle doit être configurée.
S'il vous plaît trouver plus d'informations sur cette vanne ici .
Spring Boot prend en charge la configuration de cette vanne via application.properties via les propriétés server.Tomcat.remote_ip_header et server.Tomcat.protocol_header.
J'avais exactement le même cas d'utilisation de haproxy en tant qu'équilibreur de charge avec la configuration ci-dessous, ce qui m'inquiétait. La seule chose est que l'adresse IP du client est dans request.getRemoteAddr()
et non dans l'en-tête "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 }
Dans application.properties:
server.use-forward-headers=true
Essayez de définir la règle de réécriture de la manière suivante: https: // proxyserver: 4433/appname >> suivant >> http: // appserver: 8080/appname
Et définissez ensuite le contexte de votre application sur "nomapplication" server.context-path =/appname
Donc, localement, vous pouvez utiliser http: // appserver: 8080/appname et vous pouvez accéder via le proxy inverse via https: // serveur de pro: 4433/appname
Depuis que j'utilise JBOSS, modifications dans standalone.xm de jboss:
<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>
Tomcat aurait une configuration similaire pour informer Tomcat (proxy-address-forwarding = "true") de respecter l'adresse de transfert de proxy.
Avez-vous essayé de mettre
server.context-path=/appname
Au démarrage de printemps?