无法忽略带有NS标志的mod_rewrite内部重定向

时间:2014-06-17 08:19:42

标签: apache mod-rewrite url-rewriting

我在mod_rewrite文件中定义了一些.htaccess规则,一个用于重写从/rwtest/source.html/rwtest/target.html的网址路径,另一个规则禁止直接访问{ {1}}。也就是说,希望查看/rwtest/target.html内容的所有用户都必须在其网址栏中输入/rwtest/target.html

我试图在禁止规则中使用/rwtest/source.html标志来防止重写的URL被拒绝,但看起来这个标志不区分第一个请求和内部重定向。似乎NS应该完成这项工作,但我确定我误解了一些事情。

有人可以澄清这种行为吗?究竟是什么使这个内部重定向不是NS标志可以忽略的内部子请求?

详细说明:

这是我的完整NS文件:

.htaccess

我在Windows 7 x64上运行Apache 2.4.9,但我在Linux上观察到Apache 2.4.3上的类似行为。这是Options +FollowSymLinks -Multiviews RewriteEngine on RewriteBase /rwtest # Forbid rule. Prohibit direct access to target.html. Note the NS flag. RewriteRule ^target.html$ - [F,NS] # Rewrite rule. Rewrite source.html to target.html. RewriteRule ^source.html$ target.html 请求的日志输出。

/rwtest/source.html

的变通方法

我发布了一些解决方法below

1 个答案:

答案 0 :(得分:11)

有几种解决方法,每种都有其优缺点。作为免责声明,我只在.htaccess上下文中对它们进行了测试。


解决方法1.检查空REDIRECT_STATUS

添加RewriteCond检查以查看%{ENV:REDIRECT_STATUS}是否为空。如果它为空,则当前请求不是内部重定向。

赞成

  • 确定内部重定向的最直接方法。

缺点

  • 缺乏文档。 Custom Error Responses上的页面简要提到了这个变量:

      

    REDIRECT_环境变量是根据重定向之前存在的环境变量创建的。它们使用REDIRECT_前缀重命名,即HTTP_USER_AGENT变为REDIRECT_HTTP_USER_AGENT。保证设置REDIRECT_URLREDIRECT_STATUSREDIRECT_QUERY_STRING,并且只有在错误条件之前存在其他标头时才会设置其他标头。

    我已尝试REDIRECT_中的所有其他RewriteCond变量,但除REDIRECT_STATUS之外的所有变量均为空内部重定向。为什么REDIRECT_STATUSmod_rewrite中的特殊问题仍然是个谜。

实施例

# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^target.html$ - [F]

# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html

这种方法的功劳归到URL rewrite : internal server error


解决方法2.使用END

暂停重写规则处理

L标志不同,即使内部重定向,END也会停止重写规则。

赞成

  • 简单。只是一个额外的旗帜。

缺点

  • 无法充分控制要处理的规则和要跳过的规则。

实施例

# Forbid rule. Prohibit direct access to target.html.
RewriteRule ^target.html$ - [F]

# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html [END]

有关详细信息,请参阅END flag


解决方法3.与THE_REQUEST

中的原始网址匹配
  

%{THE_REQUEST}

     

浏览器向服务器发送的完整HTTP请求行(例如,“GET /index.html HTTP / 1.1”)。

THE_REQUEST不会因内部重定向而发生变化,因此您可以对其进行匹配。

赞成

  • 即使在第二轮网址处理中,也可用于匹配原始网址。

缺点

  • 比其他方法复杂得多。强制使用RewriteCond只需一个RewriteRule即可。

  • 与未转义(解码)的完整网址匹配,与大多数其他变数不同。

  • 在多个RewriteRule中使用不方便。可以在每RewriteCond之上复制RewriteRule,或者可以将值导出到环境变量(请参阅示例)。两种骇客的替代品。

实施例

# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)"  # extract path from request line
RewriteCond %1 ^/rwtest/target.html$
RewriteRule ^ - [F]

# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html

或者,将路径导出到环境变量并在多个RewriteRule中使用它。

# Extract the original URL and save it to ORIG_URL.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)"  # extract path from request line
RewriteRule ^ - [E=ORIG_URL:%1]

# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/target.html$
RewriteRule ^ - [F]

# Rewrite rule. Rewrite source.html to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/source.html$
RewriteRule ^ target.html