我的 Apache 服务器上有以下
.htaccess
文件,该文件不起作用
<If "%{HTTP_HOST} == 'www.example.com'">
RewriteCond %{REMOTE_ADDR} !^192\.168\.8\.8$
RewriteRule .* - [F]
RewriteRule ^([A-Za-z0-9_-]+)$ index.php?p=$1 [NC,L]
</If>
代码在没有 if 语句的情况下也可以正常工作。 但使用 if 语句
RewriteRule ^([A-Za-z0-9_-]+)$ index.php?p=$1 [NC,L]
不起作用。它抛出“404 Not Found 错误”
<If "%{HTTP_HOST} == 'www.example.com'"> RewriteCond %{REMOTE_ADDR} !^192\.168\.8\.8$ RewriteRule .* - [F] RewriteRule ^([A-Za-z0-9_-]+)$ index.php?p=$1 [NC,L] </If>
“问题”是因为 mod_rewrite 指令嵌入在
<If>
表达式中。在请求被映射回文件系统之后,<If>
块才被合并。在这种情况下, RewriteRule
pattern 匹配绝对文件系统路径,而不是相对 URL 路径,因此上面的第二条规则将不会按预期匹配。
因此,规则需要像这样重写:
RewriteRule ^/abs/file/path/to/docroot/([A-Za-z0-9_-]+)$ index.php?p=$1 [L]
或者,更简单地,删除字符串开头锚点 - 尽管这确实会使匹配有些模糊:
RewriteRule /([A-Za-z0-9_-]+)$ index.php?p=$1 [L]
或者,最好完全避免使用
<If>
构造,因为您可能会与其他指令(在 <If>
构造之外)发生意外冲突。例如:
RewriteCond %{HTTP_HOST} =www.example.com
RewriteCond %{REMOTE_ADDR} !^192\.168\.8\.8$
RewriteRule ^ - [F]
RewriteCond %{HTTP_HOST} =www.example.com
RewriteRule ^([A-Za-z0-9_-]+)$ index.php?p=$1 [L]
(第二条规则中不需要
NC
标志,因为您已经在正则表达式中匹配 A-Z
和 a-z
。另外,在第一条规则中使用 ^
而不是 .*
,因为您不这样做不需要实际匹配这里的任何内容。)
如果您有许多此类规则仅适用于这一台主机,那么您可以反转逻辑并跳过当请求的主机不预期时遵循的N规则。例如:
# Skip the next 2 rules if the requested host is not "www.example.com"
RewriteCond %{HTTP_HOST} !=www.example.com
RewriteRule ^ - [S=2]
RewriteCond %{REMOTE_ADDR} !^192\.168\.8\.8$
RewriteRule ^ - [F]
RewriteRule ^([A-Za-z0-9_-]+)$ index.php?p=$1 [L]