【问题标题】:Apache Rewrite (mod_rewrite) cannot rewrite, if directory name is same as another directory under root, such as “lib”, on LinuxApache Rewrite (mod_rewrite) 无法重写,如果目录名称与根目录下的另一个目录相同,例如“lib”,在 Linux
【发布时间】:2018-02-19 20:09:21
【问题描述】:

我有一个网站在 Amazon EC2 上的 Ubuntu 16.04.3 上运行。这是uname -a的结果

Linux ip-172-31-34-232 4.4.0-1050-aws #59-Ubuntu SMP Tue Jan 30 19:57:10 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

我网站的根目录是:

/var/www/html/www

所以我的 000-default.conf 中有这么一行:

DocumentRoot /var/www/html/www

我在根目录中有一个名为lib 的目录。目录的完整路径为:

/var/www/html/www/lib

里面有一些css和js文件。例如:

/var/www/html/www/lib/customized.css

完全没有问题,直到我开始使用 Apache Rewrite (mod_rewrite)。

如果我不写任何重写规则,那很好。 lib/customized.css 可以从http://hostname/lib/customized.css 访问,HTTP 状态码为 200,表示一切正常。

如果我为其他目录重写,那很好。例如:

RewriteRule ^\/img\/.*$ $0 [L]

写完上面那行之后,我仍然可以访问img 下的任何内容。例如,我可以从http://hostname/img/logo.png 访问img/logo.png

但是,如果我想为 lib 做同样的事情,请添加:

RewriteRule ^\/lib\/.*$ $0 [L]

或将现有行更改为

RewriteRule ^\/(img|lib)\/.*$ $0 [L]

lib 下的所有内容都变得无法访问。我会得到:

403 Forbidden

lib 下的任何内容(完整路径:/var/www/html/www/lib)。

这似乎发生在文档根目录下名为lib 的目录中。如果我创建一个指向lib 但命名为lib2 的符号链接,并编写此重写规则:

RewriteRule ^\/lib(\/.*)$ /lib2/$1 [L]

或者,如果我在img 中创建一个指向../lib 的符号链接,并且仍然命名为lib,并编写此重写规则:

RewriteRule ^\/lib(\/.*)$ /img/lib/$1 [L]

一切都像一个魅力。没有 403。只有 200。

更糟糕的是,此错误在 Windows 或 Raspberry Pi Zero W 上的 Raspbian 上不存在(请参阅更新 3)。在将它们上传到 Amazon EC2 之前,我在 Windows 和 Raspberry Pi Zero W(参见更新 3)上测试了我的重写规则,只是为了找到这个奇怪的错误。

我还检查了error.log,发现这是可访问的案例(img 下的文件,无关信息省略):

[rid#7fc9349cc0a0/initial] init rewrite engine with requested uri /img/logo.png
[rid#7fc9349cc0a0/initial] applying pattern '^\\/(img|lib)\\/.*$' to uri '/img/logo.png'
[rid#7fc9349cc0a0/initial] rewrite '/img/logo.png' -> '/img/logo.png'
[rid#7fc9349cc0a0/initial] local path result: /img/logo.png
[rid#7fc9349cc0a0/initial] prefixed with document_root to /var/www/html/www/img/logo.png
[rid#7fc9349cc0a0/initial] go-ahead with /var/www/html/www/img/logo.png [OK]

而且,这是针对无法访问的情况(lib 下的文件,省略了无关信息):

[rid#7fc9349ce0a0/initial] init rewrite engine with requested uri /lib/zenscroll-4.0.0/zenscroll-min.js
[rid#7fc9349ce0a0/initial] applying pattern '^\\/(img|lib)\\/.*$' to uri '/lib/zenscroll-4.0.0/zenscroll-min.js'
[rid#7fc9349ce0a0/initial] rewrite '/lib/zenscroll-4.0.0/zenscroll-min.js' -> '/lib/zenscroll-4.0.0/zenscroll-min.js'
[rid#7fc9349ce0a0/initial] local path result: /lib/zenscroll-4.0.0/zenscroll-min.js
[rid#7fc9349ce0a0/initial] go-ahead with /lib/zenscroll-4.0.0/zenscroll-min.js [OK]
[rid#7fc9349ca790/initial/redir#1] init rewrite engine with requested uri /error.php
...
... (error.php is a customized ErrorDocument, omitted)
...
[authz_core:error] [pid 13179] [client 61.149.87.39:57002] AH01630: client denied by server configuration: /lib/zenscroll-4.0.0

如果该目录与根目录下的另一个目录同名,则mod_rewrite 似乎无法以 document_root 为前缀。对于我来说,它是 lib/lib 同名。

所以我在根目录下创建了一个名为img 的目录,即/img,然后砰! img(完整路径:/var/www/html/www/img)下的文件也无法访问!

我目前的解决方案是在/var/www/html/www 下创建一个名为lib2 的链接,然后像这样重写:

RewriteRule ^\/lib(\/.*)$ /lib2/$1 [L]

我不想重命名lib 目录,因为在 Windows 和 Raspbian 上一切正常(参见更新 3)。还有其他解决方案吗?例如,我可以:

  1. 将 Ubuntu 上的 apache 更新到解决此错误的较新版本(不起作用,请参阅更新 1),或者
  2. 告诉 apache 在实际尝试访问 /lib 之前应该添加前缀?

Ubuntu 上的 Apache(版本号似乎有点过时了,但我不知道如何升级到比 Ubuntu 提供的更新的版本):

Package: apache2
Status: install ok installed
Priority: optional
Section: httpd
Installed-Size: 489
Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
Architecture: amd64
Version: 2.4.18-2ubuntu3.5

Raspbian 上的 Apache:

Package: apache2
Status: install ok installed
Priority: optional
Section: httpd
Installed-Size: 577
Maintainer: Debian Apache Maintainers <debian-apache@lists.debian.org>
Architecture: armhf
Version: 2.4.25-3+deb9u3

Windows 上的 Apache:

AH00455: Apache/2.4.27 (Win32) OpenSSL/1.0.2l PHP/7.1.9 configured -- resuming normal operations
AH00456: Apache Lounge VC14 Server built: Jul  9 2017 11:48:22

更新 1

通过 ppa:ondrej/apache2 将 Apache 更新到 2.4.29,但没有运气。它仍然存在 Windows 和 Raspbian(参见更新 3)所没有的相同问题。

Package: apache2
Status: install ok installed
Priority: optional
Section: httpd
Installed-Size: 504
Maintainer: Debian Apache Maintainers <debian-apache@lists.debian.org>
Architecture: amd64
Version: 2.4.29-2+ubuntu16.04.1+deb.sury.org+2

更新 2

apache2.conf中有这么几行:

<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
</Directory>

我认为/lib 被拒绝是因为它是/ 的一部分,所以我将其修改为:

<Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all granted
</Directory>

并重新启动 Apache2。仍然没有运气。 403 禁止。

更新 3

重新检查 Raspbian。使用 Raspbian Pi Zero W 的 Raspbian 也出现了同样的问题。

可能是因为浏览器缓存没问题。我的错。现在我认为这不是 Ubuntu 特有的错误,而是 Linux 特有的错误。

【问题讨论】:

    标签: apache .htaccess ubuntu mod-rewrite ubuntu-16.04


    【解决方案1】:

    默认情况下,RewriteRule 中的目标(或替换字符串)假定为文件路径。使用 [PT] 标志会使其被视为 URI。

    来自:RewriteRule Flags

    默认情况下,重写目标被假定为首先是文件路径(绝对路径),然后是 URI(DocumentRoot 的相对路径)。因此,最终的解决方案是在重写规则中使用[PT]标志:

    RewriteRule ^\/(img|lib)\/.*$ $0 [PT]
    

    现在可以使用了!

    [L] 不再是必要的,因为 [PT] 意味着 [L]。

    【讨论】:

      猜你喜欢
      • 2020-04-11
      • 2013-01-05
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 2020-04-02
      相关资源
      最近更新 更多