Apache Rewrite(mod_rewrite)无法重写,如果目录名与root下的另一个目录相同,例如Linux上的“lib”

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Apache Rewrite(mod_rewrite)无法重写,如果目录名与root下的另一个目录相同,例如Linux上的“lib”相关的知识,希望对你有一定的参考价值。

我在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下访问任何内容。例如,我可以从img/logo.png访问http://hostname/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]

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

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

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

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

我还检查了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更新为解决此bug的较新版本 (不工作,见更新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

UPDATE 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

UPDATE 2

apache2.conf中有这样的行:

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

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

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

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

UPDATE 3

重新检查Raspbian。 Raspberry Pi Zero W在Raspbian上发生了同样的问题

可能由于浏览器缓存而没问题。我的错。现在我认为这不是特定于Ubuntu的bug,而是针对Linux的。

答案

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

来自:RewriteRule Flags

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

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

它现在有效!

[L]不再需要,因为[PT]暗示[L]。

以上是关于Apache Rewrite(mod_rewrite)无法重写,如果目录名与root下的另一个目录相同,例如Linux上的“lib”的主要内容,如果未能解决你的问题,请参考以下文章

如果 .htaccess 使用 mod_rewrite,则 Apache httpd.conf mod_rewrite 取消

Debian/Ubuntu下安装Apache的Mod_Rewrite模块的步骤

在Apache中使用mod_rewrite模块重写URL

Apache mod_rewrite 和多个域

mod_rewrite 的问题 // Apache 2.2 // OpenSUSE 11.3

CodeIgniter 删除 index.php apache mod_rewrite