16

我在 tomcat 上有一个 Web 应用程序http://localhost:8080/WebApp/

我已经配置了 Apache 2 (mod_proy),以便本地主机可以直接访问 Web 应用程序,而无需端口和名称:例如http://localhost

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

index.html 正确显示在http://localhost. 但是如果一个 servlet 重定向:

@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

4

5 回答 5

14

感谢 Stuart 和他对这个博客的链接,我找到了一个解决方案: Reverse Proxying Tomcat Web Applications Behind 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/.../WebAppURL,而不是/WebApp在开头。

WebApp唯一的缺点是您的 Web 应用程序中不能有任何子文件夹

于 2013-08-26T07:28:25.810 回答
4

我也有这个问题,花了一些时间。我相信,如果您将 apache httpd 配置更改为以下内容,您的重定向将起作用:

<VirtualHost localhost:80>
    ProxyPreserveHost On

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

    ProxyPassReverseCookiePath /WebApp /
</VirtualHost>

这是因为 ProxyPreserveHost 已打开,因此 tomcat 响应标头将包含代理标头(即 Location 标头http://localhost/WebApp而不是)。http://localhost:8080/WebApp

作为脚注:这也适用于您想要更改您的 webapps 上下文。假设您想将公开可见的上下文更改为可以使用以下内容的上下文:

<VirtualHost localhost:80>
    ProxyPreserveHost On

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

    ProxyPassReverseCookiePath /WebApp /context
</VirtualHost>

作为参考,我发现这篇博文非常有帮助:Reverse Proxying Tomcat Web Applications Behind Apache

于 2013-12-11T14:52:13.840 回答
0

您已经使用 AJP Connector 来连接 apache2 和 tomcat ,这将是完美的解决方案。

如果您需要如何配置,请告诉我,我会解释这个细节

于 2013-08-20T10:58:48.597 回答
0

使用转发而不是重定向

我认为您的问题是使用 sendRedirect。调用 sendRedirect 实际上是假设向浏览器显示 URL 已被重定向。如果你想隐藏你需要使用转发。在你的servlet中试试这个而不是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 );
} 

在您的 context.xml 中设置 crossContext = "true",以便您可以将请求转发到其他 Web 应用程序。

<Context crossContext="true" ....../>
于 2013-08-21T05:21:08.647 回答
0

我在尝试将 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's 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 webmaster@localhost
    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>

完毕。现在转到终端并点击以下命令。

  1. sudo a2enmod proxy_http(用于 http 重定向)。
  2. sudo a2enmod proxy_wstunnel(用于 websocket 重定向)
  3. sudo service apache2 restart
  4. 在端口 8080 上运行您的应用程序服务器
于 2016-05-19T14:33:18.850 回答