【问题标题】:How to add "everything else" rule to mod_rewrite如何将“其他所有”规则添加到 mod_rewrite
【发布时间】:2012-08-21 21:06:54
【问题描述】:

我怎样才能让mod_rewrite 重定向到某个页面,或者如果没有其他规则得到满足,可能只是抛出 404?这是我的.htaccess 文件中的内容:

RewriteEngine on

RewriteRule ^\. / [F,QSA,L]
RewriteRule ^3rdparty(/.*)$ / [F,QSA,L]

RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^((images|upload)/.+|style.css)$ $1 [L]

RewriteRule ^$ special [QSA]
RewriteRule ^(special|ready|building|feedback)/?$ $1.php [QSA,L]
RewriteRule ^(ready|building)/(\d+)/?$ show_property.php?type=$1&property_id=$2 [QSA,L]

RewriteRule . error.php?code=404 [QSA,L]

如果用户尝试访问此处未明确指定的任何内容,则应该将用户发送到error.php(顺便说一句,抛出 404 的正确方法是什么?)。但是,它将用户从每个页面发送到error.php。如果我删除最后一条规则,其他一切都正常。

我做错了什么?

【问题讨论】:

    标签: apache mod-rewrite


    【解决方案1】:

    发生的情况是,当您进行重写时,您会将用户发送到新 URL,然后再次评估这些重写规则。最终不会触发其他重定向规则,它将到达最终规则并始终重定向到 error.php 页面。

    所以你需要设置一些重写条件来避免这种情况发生。

    【讨论】:

      【解决方案2】:

      重写引擎循环,因此您需要在最终重写到error.php之前通过成功的重写。可能是这样的:

      RewriteCond %{REQUEST_URI} !^/$
      RewriteCond %{REQUEST_URI} !^/(special|ready|building|feedback|show_property)\.php
      RewriteCond %{REQUEST_URI} !^/((images|upload)/.+|style.css)$
      RewriteRule ^ error.php?code=404 [QSA,L,R=404]
      

      每个条件都确保 URI 不是您的其他规则重写的其中之一。

      R=404 将作为“404 Not Found”重定向到 error.php 页面。


      不幸的是,它不起作用 - 它允许访问服务器上的所有文件(大概是因为需要满足所有条件)。我尝试了另一种解决方案:

      其他东西一定是漏掉了,尽管当我在一个空白的 htaccess 文件中测试你的规则加上这些最后,它似乎工作。您可以尝试其他一些不太好的方法,但由于您实际上并未将浏览器重定向到任何地方,因此它将对客户端隐藏。

      您在所有规则的末尾都有一个 QSA 标志,您可以在应用规则后向查询字符串添加一个唯一参数,然后检查它。示例:

      RewriteCond %{REQUEST_FILENAME} -f
      RewriteRule ^((images|upload)/.+|style.css)$ $1?_ok [L,QSA]
      

      然后在最后:

      RewriteCond %{QUERY_STRING} !_ok
      RewriteRule ^ error.php?code=404&_ok [QSA,L,R=404]    
      

      【讨论】:

      • 嗯,这可以解决问题,但它需要复制正则表达式,这不是一件好事。还有其他方法吗?
      • 不幸的是,它不起作用 - 它允许访问服务器上的所有文件(大概是因为需要满足所有条件)。我尝试了另一种解决方案:RewriteCond %{REQUEST_URI} !^((images|upload)/.+|style.css|(special|ready|building|feedback|property).php)$,然后是RewriteRule . - [QSA,L,R=404],但它也不起作用:(
      • 这个解决方案的问题是,如果用户知道“_ok”位,就有可能绕过重写规则。没有太大的弱点,但我只是有点偏执。
      【解决方案3】:

      理论上如果没有匹配的规则(并且请求的URL不存在),它已经是404了。所以我认为最简单的解决方案是使用ErrorDocument,然后重写它:

      RewriteEngine On
      
      ErrorDocument 404 /404.php
      RewriteRule ^404.php$ error.php?code=404 [L]
      
      # All your other rules here...
      

      您可以对任何其他 HTTP 错误代码执行相同操作。

      【讨论】:

      • 重点是,如果没有一个规则匹配,但是url存在,我还是想抛出404。
      • @Septagram:好的,但我需要问一下……为什么要为完全有效的 URL 抛出 404?
      • 这是为了避免意外造成漏洞。我想明确指定用户可以访问什么,并假设他不能访问其他所有内容。我对网络编程比较陌生,我不确定这是一个好还是坏的做法......
      【解决方案4】:

      这里的问题是mod_rewrite完成URL重写后,又重新提交给mod_rewrite再传一遍。因此,[L] 标志只会使规则持续到当前通过。正如this question 中更好的解释,mod_rewrite 从 Apache 版本 2.3.9 开始,现在支持另一个标志 - [END],这使得当前的 mod_rewrite 通过最后一个。对于 Apache 2.2,提供了许多解决方案,但是由于其中一个有点笨拙,另一个不起作用,我当前的解决方案是添加另外两个规则,允许访问一组特定的文件,同时为所有内容发送 404其他:

      RewriteRule ^((images|upload)/.+|style.css|(special|ready|building|feedback|property).php)$ - [QSA,L]
      RewriteRule .* - [QSA,L,R=404]
      

      【讨论】:

        【解决方案5】:

        我认为你的最后一条规则应该是

        RewriteRule ^(.*)$ error.php?code=404&query=$1 [QSA,L]
        

        您可以省略括号和 $1 参数,但了解用户尝试实现的目标可能很有用。

        希望,这可以解决问题!

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-29
          相关资源
          最近更新 更多