web-dev-qa-db-fra.com

Spring-boot avec Tomcat intégré derrière le proxy Apache

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?

23
Rop

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.

17
Igor Mukhin

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.

4
Dave Syer

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.

2
Newbie

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
1

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.

0
Sagar Mody

Avez-vous essayé de mettre

  server.context-path=/appname

Au démarrage de printemps?

0
Piotr Gwiazda