为什么mod_rewrite处理[L]标志之后的规则

时间:2012-12-26 10:05:06

标签: apache .htaccess mod-rewrite url-rewriting

有规则:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) dir/index.php?$1 [L]
RewriteRule dir/index\.php.* - [F]

为什么处理最后一条规则并为所有请求返回Forbidden?

我需要,如果找不到文件或目录,则不应处理下一条规则。

下一个例子也不适合我:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .? - [S=1]
RewriteRule dir/index\.php.* - [F]
RewriteRule (.+) dir/index.php?$1

对于所有请求,它仍然会返回Forbidden。

2 个答案:

答案 0 :(得分:2)

  

为什么处理最后一条规则并为所有请求返回Forbidden?

请求网址foobar时:

  • 两个条件(第2,3行)匹配
  • 模式匹配,生成的网址变为dir/index.php?foobar(第4行)
  • [L]标志导致重写停止 - 它不会阻止Apache再次访问重写的URL,因为它已经更改(见下文)。

使用dir/index.php作为输入网址:

  • 条件不匹配(第2行),因为文件存在
  • 跳至第5行
  • 模式匹配,因此禁止错误

当目录或文件名发生更改时,Apache必须重新评估各种配置部分(例如DirectoryFiles)以及“重写”路径的.htaccess文件。这就是为什么Apache可能会执行另一次迭代,即使前一个迭代以[L]标志结束。

  

最后一个字符串假定限制对UFL处理程序的直接访问。   直接访问意味着通过以下链接请求文件:domain.com/dir/index.php

我认为在第5行之前添加另一个条件应该有效:

RewriteCond %{THE_REQUEST} dir/index\.php\x20HTTP/\d\.\d$
RewriteRule . - [F]

THE_REQUEST服务器变量包含浏览器发送的请求,未应用任何重写。这对于检测浏览器请求最初的页面非常有用。

  

THE_REQUEST

     

浏览器向服务器发送的完整HTTP请求行(例如,   “GET /index.html HTTP / 1.1”)。这不包括任何额外的   浏览器发送的标头。该值尚未转义   (解码),与下面的大多数其他变量不同。

答案 1 :(得分:0)

我不确定“下一条规则”的含义。

但是如果您不希望在请求不存在的文件时执行某些规则,那么使用以下结构可能会有所帮助。 (以下代码段是从Apache RewriteRule Flags Page

复制而来的
# Is the request for a non-existent file?
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# If so, skip these two RewriteRules
RewriteRule .? - [S=2]

    RewriteRule (.*\.gif) images.php?$1
    RewriteRule (.*\.html) docs.php?$1

并且使用[R]重定向而不是[L]可能有助于为所有请求返回Forbidden的问题。