为什么RewriteCond%{REQUEST_URI}会干扰第二个NOT条件?

起初,这个规则是有效的:

DirectoryIndex index.php ErrorDocument 403 /form.html RewriteCond %{REQUEST_URI} ^/index\.php$ RewriteCond %{REQUEST_METHOD} !POST RewriteRule . - [F,L] 

这意味着http://example.comhttp://example.com/index.php只能通过POST打开。

现在的问题

我添加了这个额外的规则集:

 RewriteCond %{REQUEST_URI} !^/index\.php$ RewriteRule . - [F,L] 

现在,我再次发送POST到http://example.com但收到此错误:

 Forbidden You don't have permission to access / on this server. Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request. 

这没有任何意义,因为规则不应该抓住index.php请求发送一个403,但是好的,我扩展了第二条规则如下:

 RewriteCond %{REQUEST_URI} !^/form\.html$ RewriteCond %{REQUEST_URI} !^/index\.php$ RewriteRule . - [F,L] 

再次发送POST到http://example.com没有返回500,但我仍然收到403?!

更新1
如果我删除第一个规则集,第二个按预期单独工作。 这意味着只能访问http://example.com : http://example.com/index.phphttp://example.com/form.html

更新2
如果我使用这两个规则集并发送我的POST到http://example.com/index.php我没有收到任何错误?!

所以,只有当我发送POST到根URL时,规则才会干涉。 但为什么?

 RewriteCond %{REQUEST_URI} ^/index\.php$ RewriteCond %{REQUEST_METHOD} !POST RewriteRule . - [F,L] 

假设你的DirectoryIndex被设置为index.php并且你没有其他的指令,那么当访问http://example.com/时,它似乎是你的第一个规则块,导致403 Forbidden。 以上只允许直接POST请求到/index.php

上面的RewriteRule 模式 (单点)阻止了对http://example.com/请求处理规则。 mod_dir然后启动一个内部子请求到/index.php 。 请注意,这个子请求实际上performance为一个内部的GET请求(这是REQUEST_METHOD服务器variables的设置),所以上述条件( !POST )成功,最终请求被禁止。

将请求规范化并将/index.php任何请求外部redirect(308 – 永久redirect保留请求方法)为/是更/index.php 。 然后你可以专注于匹配/并可以忽略子请求。

 # Exception for error document (before other directives) RewriteRule ^form\.html$ - [L] # Canonicalise URL and remove "index.php" if requested RewriteRule %{REDIRECT_STATUS} ^$ RewriteRule ^index\.php$ / [R=308,L] # Only allow POST requests to the document root RewriteCond %{REQUEST_METHOD} !POST RewriteRule ^$ - [F] 

(使用F时不需要L标志,暗示L

testing之前确保浏览器caching清除。 (可能最好使用R=307 (临时)redirect进行testing以避免caching。)

 RewriteCond %{REQUEST_URI} !^/index\.php$ RewriteRule . - [F,L] 

正如你所build议的那样,这与上面的规则不冲突,它匹配//index.php以外的任何东西(当在.htaccess使用时)。 所以,不pipe请求方法如何,都禁止访问所有其他的URL。 (如上所述,它似乎是访问http://example.com/时触发403的第一条规则。)如上所述,为您的错误文档提供了一个例外,那么您不需要添加一个额外的条件。