Amortisseur à ressort avec Tomcat intégré derrière le proxy Apache
nous avons une application MVC à ressort avec Tomcat embarqué sur un appserveur dédié derrière un proxy Apache SSL.
le port SSL sur le serveur proxys est 4433, redirigeant vers le port 8080 sur l'appserveur.
donc L'URL du serveur proxy est redirigé comme:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
quand vous courez sans proxy, la première chose qui arrive est que
printemps-sécurité redirige la demande, de la forme:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
pour afficher le formulaire de connexion, par extension WebSecurityConfigurerAdapter
...
httpSecurity.formLogin().loginPage("/login") ...
...
Cela fonctionne très bien sans le proxy, mais avec proxy la redirection doit être changée, donc Spring devrait plutôt rediriger vers l'URL proxy correspondante, comme:
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
mais pas encore de succès.
je suis en train 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-end proxy server)
Nous avons configuré mod_proxy d'Apache, et vérifié qu'il envoie attendus en-têtes:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
l'application est lancée avec des 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 va continuer à rediriger localement, vers http://appserver:8080/login
qui n'est pas disponible pour les clients.
Est-il autre chose que nous devons faire pour rendre ce scénario de travail?
EDIT: Aussi, je suis préoccupé par la partie" / appname " de L'URL du mandataire. Sur le serveur d'application, l'application est ancrée à"/". Comment spring devrait-il être informé que "/appname" doit être inclus dans toutes les URLs envoyées aux clients, quand on passe par le proxy?
6 réponses
j'ai eu le même problème l'autre jour. Après un peu de débogage de la botte de printemps 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 dire à votre application de démarrage à ressort d'utiliser ces en-têtes. Donc, mettez la ligne suivante dans votre demande.propriétés (ou tout autre lieu où le Printemps Bottes comprend propriétés):
server.use-forward-headers=true
si vous faites ces deux choses correctement, chaque redirection que votre application envoie sera http://127.0.0.1:8080/[chemin] mais https://www.myapp.com/[chemin]
mise à jour 1. La documentation sur ce sujet est ici. Vous devriez le lire au moins être conscient de la propriété server.tomcat.internal-proxies
qui définit la gamme D'adresses IP pour les serveurs proxy qui peuvent être fiables.
votre mandataire a l'air bien, et l'appli backend aussi, jusqu'à un certain point, mais il ne semble pas voir le RemoteIpValve
demande modifiée. Le comportement par défaut de l' RemoteIpValve
inclut une correspondance de modèle pour l'adresse IP du mandataire (comme une vérification de sécurité) et ne modifie que les requêtes qu'il pense être d'un mandataire valide. Le modèle par défaut dans la botte de printemps à un ensemble bien connu d'adresses IP internes comme 10.*.*.*
et 192.168.*.*
, donc si votre proxy n'est pas sur l'un de ces, vous devez explicitement configurer, 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 properties, ce qui signifie que vous devez double escape the backslashes).
Vous pouvez voir ce qui se passe dans le RemoteIpValve
si vous définissez
logging.level.org.apache.catalina.valves.RemoteIpValve=DEBUG
ou définir un point d'arrêt.
une solution typique à ce problème est de laisser le proxy gérer toute réécriture requise. Par exemple, dans Apache, vous pouvez utiliser le rewrite_module et/ou headers_module pour corriger les en-têtes. Comme autre exemple, Nginx gère ce cas et d'autres similaires automatiquement pour vous après avoir configuré des serveurs amont.
En réponse aux commentaires:
Qu'est-ce que la configuration de démarrage à ressort remote_ip_header et protocol_header valeurs?
oublions la botte de printemps pendant un moment. Tomcat, le conteneur servlet intégré, dispose d'une valve appelée RemoteIpValve. Cette valve est un port de L'Apache remotip_module. Le but principal de cette soupape est de traiter "l'agent utilisateur qui a introduit la demande comme l'agent utilisateur d'origine" aux "fins d'autorisation et de journalisation". Pour cette vanne pour être utilisée, elle doit être configurée.
Veuillez trouver plus d'informations sur cette vanne ici.
démarrage à ressort prend en charge la configuration de cette valve via l'application.propriétés à travers le serveur.tomcat.remote_ip_header et serveur.tomcat.propriétés de protocol_header.
j'ai eu exactement le même cas en utilisant haproxy comme équilibreur de charge avec la configuration ci-dessous, ce qui m'a inquiété. La seule chose, c'est l'IP du client est dans request.getRemoteAddr()
et pas "X-Forwarded-For"
en-tête
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 }
en application.propriétés:
server.use-forward-headers=true
avez-vous essayé de définir
server.context-path=/appname
Dans La Botte De Printemps?
Essayez de définir la règle de Réécriture comme: >>avant>> http://appserver:8080/appname
puis définissez le contexte de votre application à "appname" serveur.contexte-path=/appname
Donc localement, vous pouvez exécuter par http://appserver:8080/appname et via Proxy Inverse vous auriez accès via
depuis que j'utilise JBOSS, change en autonome.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 forwarding du proxy.