从虚拟主机的 URL 中删除 Tomcat 上下文(mod_jk、mod_rewrite)

Posted

技术标签:

【中文标题】从虚拟主机的 URL 中删除 Tomcat 上下文(mod_jk、mod_rewrite)【英文标题】:Removing Tomcat context from URLs for a virtual host (mod_jk, mod_rewrite) 【发布时间】:2011-01-05 01:17:52 【问题描述】:

我有一个 Tomcat 实例,其中包含许多 webapp,每个都可以通过它的 /Context 访问。 Tomcat 落后于 httpd(实际上是 Debian Apache2),配置了虚拟主机来服务每个应用程序/上下文。 Tomcat 连接使用 mod_jk。

当我不关心从 url 中删除上下文时,这很好用:当请求虚拟域的根时,请求被重定向到 domain.com/Context。

但是对于一个应用程序,我确实想要删除上下文。我相信这可以通过使用 mod_rewrite 来完成,并将重写的 url 传递给 mod_jk 以传递到正确的 Tomcat 上下文。所以我的 Debian Apache2 站点可用文件如下所示:

NameVirtualHost *

<VirtualHost *>
    ServerName domain.be

    DocumentRoot /home/webapp/app/static/domain/

    RewriteEngine on
    RewriteRule ^/(.*)$ /Context/$1 [L,PT]
    RewriteLog "/var/log/apache2/domain-rewrite.log"
    RewriteLogLevel 4

    JkLogFile     /var/log/apache2/domain-mod_jk.log
    JkLogLevel    debug
    JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
    JkMount /Context w1
    JKMount /Context* w1
    JkOptions +ForwardURICompat

    ErrorLog /var/log/apache2/domain_error.log
    CustomLog /var/log/apache2/domain_access.log combined
    LogLevel warn

</VirtualHost>

根据文档,[PT] 标志和 +ForwardURICompat 选项应该会导致将重写的 URL 传递给 jk_mod。然而,这似乎并没有发生。

正在重写 URL,但似乎 mod_jk 忽略了它:例如,对 domain.be/Context 的请求被重写为 /Context/Context - 但仍作为 /Context 交给 mod_jk。

有什么想法吗?顺便说一句,我目前无法使用 mod_proxy。

谢谢

【问题讨论】:

【参考方案1】:

我一直在使用它并取得了巨大的成功:

RewriteEngine On
RewriteCond %REQUEST_URI !^/(Context/.*)$
RewriteRule ^/(.*)$ /Context/$1 [P,L]

关于您的情况的说明:

您需要让 mod_proxy 工作,否则[P] 将被忽略,请求将被转发而不是代理。没有办法解决这个问题。 +ForwardURICompat是mod_jk的一部分,重写后生效。 mod_jk 忽略该请求,因为它永远不会到达那里。您需要 RewriteCond(上图)来防止对 /Context 的请求被重写。

我目前正在寻找一种无需 mod_rewrite 而是使用 just mod_jk and Tomcat <Host>'s 来实现此目的的方法。但是我在 apache、mod_jk 和 Tomcat 主机上玩得很好时遇到了麻烦。以上应该适合你。

【讨论】:

【参考方案2】:

@Josh,我认为如果 tomcat 执行任何重定向,此解决方案将不起作用。这是典型的情况,例如在要求登录的应用程序中。当用户未通过身份验证时,应用程序将重定向到 /login 之类的内容,但 tomcat 将附加当前上下文,如 /context/login 中,因此最后上下文确实显示在 URL 中。

正如您在其他问题/回复中提到的,仅使用 mod-jk 和 tomcat 虚拟主机是一种选择,但您需要将应用程序部署为 ROOT.war,这可能不是那么简单。有一种解决方法,因此您的应用程序可以直接放入 tomcat webapps 文件夹,但正如我所描述的here,服务器将部署该应用程序至少两次。

如果 RewriteRule[P] 加上 JkOptions +ForwardURICompat 可以工作,那就太好了,但事实并非如此。顺便说一句,我已经对此进行了测试,并且我知道 mod_proxy 确实可以工作,因为我将我的网站代理到 cnn.com 并且我在我的网站 URL 下获得了他们的页面。以下是您可以看到正在使用代理的请求的日志顺便说一句:

127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:12:56:34 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/login
127.0.0.1 - - [15/Dec/2011:12:56:49 --0500] [localhost/sid#1008ef278][rid#1009aaca8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/login [OK]
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/j_spring_security_check
127.0.0.1 - - [15/Dec/2011:12:57:15 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/j_spring_security_check [OK]
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (2) forcing proxy-throughput with http://localhost/nestorurquiza-app/
127.0.0.1 - - [15/Dec/2011:13:08:41 --0500] [localhost/sid#1008ef278][rid#1009980a8/initial] (1) go-ahead with proxy request proxy:http://localhost/nestorurquiza-app/ [OK]

【讨论】:

你说得对,我原来的解决方案不是最好的方法,而且充满危险。但是自从发布之后,我使用 Tomcat VirtualHosts 取得了很大的成功。尽管没有听说人们经常使用它,但它绝对是人们在这种情况下想要使用的,而且在创建之后一点也不难。【参考方案3】:

我会保留我原来的答案,但这是错误的。正确的方法是使用 Tomcat 虚拟主机:

http://tomcat.apache.org/tomcat-6.0-doc/virtual-hosting-howto.html

上面链接中的官方演练正是我现在多次使用的。我不会在这里尝试归结为它。

这个概念与 Apache Vhost 相同。创建一个虚拟主机(例如something.yourtdomain.com)并将您的webapp 部署到该虚拟主机的ROOT 应用程序(/),一切就绪。这样,如果您已经有一个 ROOT webapp,您可以在不同的域中拥有另一个,而先前的将不受影响。

正如 Nestor 所提到的,Apache 重写规则不会处理标签库和框架之类的东西,它们会根据上下文根自动为您创建链接/表单操作/等。在这种情况下,他们将创建正确的上下文根 (/)。

【讨论】:

如果您不知道,您实际上可以将应用程序留在 webapps 目录中,只需将 appBase 设置为应用程序的完整路径。 --- 示例:主机>【参考方案4】:

使用 mod_proxy_ajp 代替 mod_jk,如下所示:

<VirtualHost *:80>
  ServerName domain.be

  DocumentRoot /home/webapp/app/static/domain/

  ...

  ProxyPass /Context ajp://localhost:8009/Context
  ProxyPass / ajp://localhost:8009/Context/

  ...
</VirtualHost>

【讨论】:

如果 Tomcat 执行任何重定向,这仍然不起作用。它实际上根本没有改变根本问题。没有答案。【参考方案5】:

按照 Nestor Urquiza 的回答给出的提示,我设法通过在 tomcat 的 server.xml 中定义额外的主机来解决这个问题,因为如上所述,j_security_check 请求由 tomcat 回答,向浏览器发出转发指令,其中不可避免地包含上下文名称这样尝试登录的用户就会收到 408 错误。因此,在 Apache VirtualHost JkMount /* worker1 指令中进行真正的直通可以通过将预期的上下文设置为 ROOT 来实现。

Apache httpd.conf [和/或包含的 *.conf ] 文件:

<!-- the subdomain -->

<VirtualHost *:80>
    ServerName appWelcome.example.org
    ServerAlias www.appWelcome.example.org
    JKMount /* worker1
</VirtualHost>

<!-- with mod_jk set up -->

LoadModule    jk_module modules/mod_jk.so
JWorkersFile  /etc/apache2/workers.properties
JkShmFile     /var/log/apache2/mod_jk.shm

因此,要将对子域 http://appWelcome.example.org/ 的所有请求直接映射到负责的 /appWelcome tomcat 上下文,appWelcome 上下文必须可通过对http://appWelcome.example.org:8080/ 的请求进行寻址

因此,tomcat server.xml 文件将为您要公开的应用程序添加一个单独的Host:。

<Server ...>
  <Service>
    <Engine defaultHost="localhost" ...>

      <Host name="appWelcome.example.org" appBase="appWelcomeBase" ... >
        <Valve ... />
      </Host>

      <Host name="localhost" appBase="webapps" ...>
        <!-- this Host is typically shipped with manager, host-manager, docs, 
          sample, examples and a default ROOT context that shows tomcat default home. -->
        <Valve ... />
      </Host>

    </Engine>
  </Service>
</Server>

请注意,必须调整权限(和 selinux 上下文,如果启用)以模仿默认的Host,如下所示:

$CATALINA_HOME/conf/Catalina/app.example.org$CATALINA_HOME/conf/Catalina/localhost

$CATALINA_HOME/appWelcomeBase$CATALINA_HOME/webapps

完成后,剩下要做的就是发出重命名并将appWelcome.war web 存档移动到创建的appBase 中自动部署(将 $CATALINA_HOME 替换为其值,例如 /var/www/ tomcat7) :

# mv $CATALINA_HOME/webapps/appWelcome.war $CATALINA_HOME/appWelcomeBase/ROOT.war

瞧!

【讨论】:

以上是关于从虚拟主机的 URL 中删除 Tomcat 上下文(mod_jk、mod_rewrite)的主要内容,如果未能解决你的问题,请参考以下文章

从 URL 中删除上下文名称 - 使用 Spring Security 的 mod_proxy_ajp

从Tomcat URL中删除文件夹名称

如果连接器端口是 8081,如何从 apache tomcat 中的 URL 中删除端口号

Tomcat删除index.php Codeigniter

如何从 Firebase 存储下载 URL 中删除查询字符串

本地服务器和 tomcat 之间的 url 上下文更改