Подтвердить что ты не робот

Отправка перенаправления в веб-приложении Tomcat за прокси-сервером Apache 2 (mod_proxy)

У меня есть веб-приложение на tomcat http://localhost:8080/WebApp/

Я сконфигурировал Apache 2 (mod_proy), чтобы веб-приложение было напрямую доступно локальным хостом с внешним портом и именем: например, http://localhost

<VirtualHost localhost:80>
    ProxyPreserveHost On
    ProxyPass / http://localhost:8080/WebApp/
    ProxyPassReverse / http://localhost:8080/WebApp/
</VirtualHost>

Указатель index.html корректно отображается на http://localhost. Но если сервлет перенаправляет:

@WebServlet(description = "...", urlPatterns = { "/login" })
public class LoginServlet extends HttpServlet
{    
    @Override
    protected void doGet(HttpServletRequest request,
                     HttpServletResponse response) throws IOException
    {
        response.sendRedirect("a.html");
    }
 }

и я использую URL http://localhost/login - меня перенаправляют на http://localhost/WebApp/a.html

Как мне получить правильное перенаправление на http://localhost/a.html?

4b9b3361

Ответ 1

Благодаря Стюарту и его ссылке на этот блог я нашел решение: Обратное проксирование веб-приложений Tomcat за Apache

Решение: ProxyPreserveHost необходимо отключить!

Причина. Если он включен, заголовки ответов, возвращаемые бэкэндом прокси, будут содержать "localhost" или реальный домен без номера порта (или 80). Таким образом, шаблон ProxyPassReverse не соответствует (из-за другого порта и если используется другое имя домена, также имя домена не будет соответствовать).

Конфигурация:

<VirtualHost localhost:80>

   ProxyPreserveHost Off
   ProxyPass /  http://localhost:8080/WebApp/
   ProxyPassReverse / http://localhost:8080/WebApp/

</VirtualHost>

Но это работает только через http, а не через ajp (я не знаю почему). Если вы все еще хотите использовать ajp, вы можете использовать следующее обходное решение - пусть Apache сделает еще одно перенаправление после неправильного перенаправления:

<VirtualHost localhost:80>

   ProxyPass /WebApp !
   ProxyPass /  ajp://localhost:8009/WebApp/
   ProxyPassReverse / ajp://localhost:8009/WebApp/

   RedirectMatch 301 ^/WebApp/(.*)$ /$1
   RedirectMatch 301 ^/WebApp$ /

</VirtualHost>

Директива ProxyPass /WebApp ! необходима для исключения пути от дальнейшей обработки в mod_proxy (поскольку директивы прокси оцениваются перед директивами перенаправления)

Затем директивы RedirectMatch перенаправляют все, указывая с /WebApp/... соответственно /WebApp на URL без /WebApp в начале.

Единственный недостаток заключается в том, что у вас не должно быть подпапок с именем WebApp в вашем веб-приложении

Ответ 2

У меня также была эта проблема и потратил на нее некоторое время. Я считаю, что если вы измените конфигурацию apache httpd на следующее, ваше перенаправление будет работать:

<VirtualHost localhost:80>
    ProxyPreserveHost On

    ProxyPass / http://localhost:8080/WebApp/
    ProxyPassReverse / http://localhost/WebApp/

    ProxyPassReverseCookiePath /WebApp /
</VirtualHost>

Это связано с тем, что заголовки ответов tomcat будут содержать заголовки прокси (т.е. заголовок Location http://localhost/WebApp, а не http://localhost:8080/WebApp), поскольку включен ProxyPreserveHost.

Как сноска: это также работает с вами, чтобы изменить ваш контекст webapps. Предположим, вы хотели изменить контекст, видимый на публике, в контекст, который вы можете использовать:

<VirtualHost localhost:80>
    ProxyPreserveHost On

    ProxyPass /context/ http://localhost:8080/WebApp/
    ProxyPassReverse /context/ http://localhost/WebApp/

    ProxyPassReverseCookiePath /WebApp /context
</VirtualHost>

Для справки я нашел этот пост в блоге чрезвычайно полезным: Обратное проксирование веб-приложений Tomcat за Apache

Ответ 3

вы используете AJP Connector для подключения apache2 и tomcat, это будет идеальное решение для этого.

если вам нужно как это настроить, скажите, что я объясню эту деталь

Ответ 4

Использовать переадресацию вместо перенаправления

Я думаю, что ваша проблема заключается в использовании sendRedirect. Вызов sendRedirect на самом деле предполагает показать браузеру, что URL-адрес перенаправлен. Если вы хотите скрыть, что вам нужно использовать переадресацию. В вашем сервлете попробуйте это вместо sendRedirect.

String servletPath = request.getServletPath();
if(servletPath.equals("/app1")){
     ServletContext ctx = request.getServletContext().getContext("/app1");
     RequestDispatcher dispatcher=ctx.getServletContext().getRequestDispatcher( "/app1/app1.html" ); // or wherever you actually keep app1.html
     dispatcher.forward( request, response );
} 

Внутри вашего контекстного .xml установите crossContext = "true", чтобы вы могли пересылать запросы другим веб-приложениям.

<Context crossContext="true" ....../>

Ответ 5

У меня была такая же проблема, когда я пытался перенаправить запрос apache2 (работающий на порт 80) на tomcat (сервер приложений, запущенный на порту 8080).

Это конфигурация, которая работает отлично.

Перейдите к /etc/apache2/sites-available/000-default.conf и добавьте следующую конфигурацию:

<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    #ServerName www.example.com

    # for redirecting the websocket requests
    ProxyPass /ws ws://localhost:7681/ 
    #ProxyPass  /ws ws://localhost:7681/

    ProxyPassReverse   /ws ws://localhost:7681/

    ServerAdmin [email protected]
    DocumentRoot /var/www/html

    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf


# for redirecting the http request 
   ProxyPass /applicationContextUrl                         '  http://localhost:8080/applicationContextUrl

   ProxyPassReverse /applicationContextUrl         http://localhost:8080/applicationContextUrl

   ProxyPassReverseCookiePath /applicationContextUrl / 
   ProxyPassReverseCookieDomain localhost applicationContextUrl
   ProxyRequests off
   ProxyTimeout 15


   ErrorLog ${APACHE_LOG_DIR}/nirad_error.log
   LogLevel debug
CustomLog ${APACHE_LOG_DIR}/nirad_access.log combined
<Proxy *>
       AddDefaultCharset off
       Order deny,allow
       Allow from all
       #Require all denied
       Require all granted
       Require local

</Proxy>
</VirtualHost>

Готово. Теперь перейдите в терминал и нажмите следующую команду.

  • sudo a2enmod proxy_http (для перенаправления http).
  • sudo a2enmod proxy_wstunnel (для перенаправления websocket)
  • и sudo service apache2 restart
  • запустите сервер приложений на порту 8080