Spring-boot со встроенным Tomcat за прокси Apache

у нас есть приложение spring-boot/spring-mvc со встроенным Tomcat на выделенном appserver за SSL-прокси Apache.

SSL-порт на proxyserver-4433, переадресация на порт 8080 на appserver.

таким образом, URL-адрес прокси-сервера пересылается как:

https://proxyserver:4433/appname   >>forward>>   http://appserver:8080/

при работе без прокси-сервера первое, что происходит, это
spring-security перенаправляет запрос, например:

http://appserver:8080/   >>redirect>>   http://appserver:8080/login

для отображения формы входа, по расширение WebSecurityConfigurerAdapter С

  ...
  httpSecurity.formLogin().loginPage("/login") ...
  ...

он отлично работает без прокси, но с прокси-сервером перенаправление необходимо изменить, поэтому Spring следует перенаправить на соответствующий прокси-URL, например:

http://appserver:8080/   >>redirect>>   https://proxyserver:4433/appname/login

но пока безуспешно.

Я пытаюсь применить это решение:

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-tomcat-behind-a-proxy-server (59.8 использовать Tomcat за передним концом прокси-сервер)

мы настроили mod_proxy в Apache и проверили, что он отправляет ожидаемые заголовки:

X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https

приложение запускается с параметрами:

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

все еще перенаправление не работает.

он будет продолжать перенаправлять локально, в http://appserver:8080/login который недоступен для клиентов.

есть ли что-нибудь еще, что нам нужно сделать, чтобы этот сценарий работал?

редактировать: кроме того, я обеспокоенный частью" / appname " в URL-адресе прокси. На appserver приложение коренится в "/". Как spring следует проинструктировать, что" /appname " должен быть включен во все URL-адреса, отправленные клиентам, при прохождении через прокси-сервер?

6 ответов


у меня была такая же проблема на днях. После некоторой отладки Spring Boot 1.3 я нашел следующее решение.

1. вы должны настроить заголовки на прокси-сервере 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. вы должны сказать, что ваше приложение Spring Boot использует эти заголовки. Поэтому поставьте следующую строку в своем заявлении.свойства (или любое другое место, где Spring Boots понимает свойства):

server.use-forward-headers=true

Если вы сделаете эти две вещи правильно, каждое перенаправление вашего приложения отправляет will не на http://127.0.0.1:8080/[путь] но автоматически в https://www.myapp.com / [путь]

обновление 1. документация по этой теме здесь. Вы должны прочитать его, по крайней мере, чтобы быть в курсе свойства server.tomcat.internal-proxies который определяет диапазон IP-адресов для прокси-серверов, которым можно доверять.


ваш прокси выглядит нормально, и так же бэкэнд приложение, до определенного момента, но он, кажется, не видит RemoteIpValve измененный запрос. Поведение по умолчанию RemoteIpValve включает соответствие шаблона для IP-адреса прокси (в качестве проверки безопасности), и он только изменяет запросы, которые он считает от действительного прокси. Шаблон по умолчанию в Spring Boot для известного набора внутренних IP-адресов, таких как 10.*.*.* и 192.168.*.*, поэтому, если ваш прокси-сервер не находится на одном из них, вам нужно явно настроить его, например,

server.tomcat.internal-proxies=172\.17\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}

(используя формат файла свойств, что означает, что вам нужно дважды избежать обратных косых черт).

вы можете видеть, что происходит в RemoteIpValve Если вы устанавливаете

logging.level.org.apache.catalina.valves.RemoteIpValve=DEBUG

или установить точку останова в нем.


типичное решение этой проблемы-позволить прокси-серверу обрабатывать любую необходимую перезапись. Например, в Apache вы можете использовать rewrite_module и/или headers_module для исправления заголовков. В качестве другого примера Nginx обрабатывает этот и другие подобные случаи автоматически после настройки вышестоящих серверов.

в ответ на комментарии:

какова конфигурация весенней загрузки remote_ip_header и protocol_header ценности?

давайте забудем Spring Boot на мгновение. Tomcat, встроенный контейнер сервлетов, имеет клапан, известный как RemoteIpValve. Этот клапан является портом Apache remotip_module. Основная цель этого клапана состоит в том, чтобы рассматривать "useragent, который инициировал запрос, как исходный useragent" для "целей авторизации и регистрации". Для того, чтобы этот клапан использовался, его необходимо настроить.

пожалуйста найдите больше информации о этот клапан здесь.

ботинок весны удобно поддерживает устанавливать этот клапан через применение.свойства через сервер.кот.remote_ip_header и сервер.кот.свойства protocol_header.


у меня был точно такой же случай с использованием haproxy в качестве балансировщика нагрузки с приведенной ниже конфигурацией, которая для меня. Единственное, что клиент IP находится в request.getRemoteAddr() и не в "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 }

в приложение.свойства:

 server.use-forward-headers=true

вы пробовали установка

  server.context-path=/appname

В Весенней Загрузке?


попробуйте установить правило перезаписи, как: https://proxyserver:4433/appname >>вперед>> http://appserver:8080/appname

а затем установите контекст приложения в " appname" сервер.context-path= / appname

таким образом, локально вы можете запустить http://appserver:8080/appname и через обратный прокси вы получаете доступ через https://proxyserver:4433/appname

поскольку я использую JBOSS, изменения в автономном режиме.ХМ из с JBoss:

<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>

Tomcat будет иметь аналогичную конфигурацию, чтобы сообщить Tomcat (proxy-address-forwarding="true") уважать адрес пересылки прокси.