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?

23
demandé sur Rop 2014-08-23 01:45:00

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.

16
répondu Igor Mukhin 2018-08-16 15:22:45

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.

4
répondu Dave Syer 2015-05-14 10:06:39

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.

2
répondu Newbie 2014-08-24 22:50:32

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
1
répondu Panagiotis Theocharis 2016-11-24 16:48:19

avez-vous essayé de définir

  server.context-path=/appname

Dans La Botte De Printemps?

0
répondu Piotr Gwiazda 2017-01-27 17:49:34

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.

0
répondu Sagar Mody 2018-06-25 03:11:43