如果 HTTP_HOST 不适用于 Reqrite 规则,则使用 htaccess

问题描述 投票:0回答:1

我的 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 错误”

apache .htaccess mod-rewrite
1个回答
0
投票
<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]
© www.soinside.com 2019 - 2024. All rights reserved.