我应该在 RewriteCond 中转义斜杠“/”吗?

我应该在 RewriteCond 中转义斜杠“/”吗?

我是否需要在 RewriteCond 中转义斜杠“/”?

目前我在.htaccess中写入以下规则:

RewriteCond %{QUERY_STRING} rp=/knowledgebase/
RewriteRule ^index\.php$ https://www.datanumen.com/knowledgebase/ [QSD,R=301,L,NC]

但是,这只适用于类似这样的 URLhttps://www.datanumen.com/fi/customer/index.php?rp=/knowledgebase/7/How-to-order-the-full-version-of-DataNumen-Access-Repair.html&language=swedish,但不适用于以下 URLhttps://www.datanumen.com/fi/customer/index.php?rp=%2Fknowledgebase%2F7%2FHow-to-order-the-full-version-of-DataNumen-Access-Repair.html&language=swedish

因此,我必须修改规则,如下所示:

RewriteCond %{QUERY_STRING} rp=/knowledgebase/ [OR]
RewriteCond %{QUERY_STRING} rp=%2Fknowledgebase%2F
RewriteRule ^index\.php$ https://www.datanumen.com/knowledgebase/ [QSD,R=301,L,NC]

但我检查https://serverfault.com/a/968916/280923上面写着“斜线 (/) 无需转义“所以我很困惑。”

如果我需要考虑所有的情况,即 '/' 的转义版本和非转义版本,那么应该总共有 4 种组合,我是否应该将它们全部添加为 RewriteCond:

rp=/knowledgebase/
rp=%2Fknowledgebase%2F
rp=%2Fknowledgebase/
rp=/knowledgebase%2F

答案1

我应该逃避斜线/RewriteCond

所谓“转义斜线”,你的真正意思是“我是否应该匹配 URL 编码的斜线?”。这完全取决于向你的服务器发出的 HTTP 请求。

但我检查https://serverfault.com/a/968916/280923并且它说“斜线 ( /) 不需要转义”。所以我很困惑。

链接的问题/答案与当前问题无关。该问题涉及 Apache 指令/正则表达式中的反斜杠转义,而不是您在此处处理的 URL 编码(或 % 编码)URL。这是两种非常不同类型的“转义”方法,用于不同的目的。

您正在处理的是 % 编码的 URL。URL 在 HTTP 请求中的显示方式。URL 的不同部分(特别是“路径”和“查询字符串”)具有不同的编码要求。特定字符是否需求是否进行 % 编码取决于它在该上下文中是否具有特殊含义。

根据定义RFC3986,斜线 ( /) 在 URL 的查询字符串部分中严格来说不需要进行 % 编码。但是,URL 编码函数(例如 PHP 和 JavaScript)通常会对此字符进行 % 编码。(我认为这主要是历史原因,因为据报道一些旧的实现无法正确处理未编码的斜线 - 参考RFC3986

然而,无论角色需求进行 URL 编码(以否定其特殊含义),任何字符都可以进行 % 编码,并且应该将其视为与文字(未编码)字符相同的行为。

是否需要匹配/(解码)或%2F(编码)取决于该字符在请求中是否是%编码。

您的问题是QUERY_STRING服务器变量不是 % 解码的,与 URL 路径匹配的RewriteRule 图案

但是……您需要同时检查 %-decoded/和 %-encoded%2F吗?大概您一直只链接到其中一个(规范)URL。因此,对非规范 URL 的任何请求都必须手动输入或由第三方错误链接。您是否同时收到对两者的请求?不重定向非规范 URL 的后果是什么?

否则,是的,您需要检查两者(以及可能的所有变体/情况)。虽然这可能只是/knowledgebase/%2Fknowledgebase%2F。但请注意,它可能是%2F(大写)或%2f(小写)。大写只是一种惯例。必须检查混合编码,例如%2Fknowledgebase/应该非常罕见。但极端情况下,这也与相同%2f%6b%6e%6f%77%6c%65%64%67%65%62%61%73%65%2f。您是否需要处理所有这些变体取决于收到此类请求的可能性以及规则不匹配的严重性。

因此,为了匹配/knowledgebase/%2Fknowledgebase%2F(不区分大小写),您可以使用类似以下命令:

RewriteCond %{QUERY_STRING} ^rp=(/|%2[Ff])knowledgebase(/|%2[Ff])

您可以避免使用字符类[Ff],而使用NC标志来使整个比较不区分大小写。例如:

RewriteCond %{QUERY_STRING} ^rp=(/|%2F)knowledgebase(/|%2F) [NC]

在 Apache 2.4 中,您可以unescape()在 Apache 表达式中使用该函数,并在进行比较之前使用RewriteCond指令对 URL 进行解码。但是,这实际上对您没有帮助,因为它不会对斜杠进行 % 解码,即,或仍按请求进行(但任何其他字符都会被 % 解码)。例如:QUERY_STRING%2F%2f

RewriteCond expr "unescape(%{QUERY_STRING}) =~ m#^rp=(/|%2[Ff])knowledgebase(/|%2[Ff])#"

这将允许您匹配rp=%2f%6b%6e%6f%77%6c%65%64%67%65%62%61%73%65%2f


或者,如果您不希望查询字符串中出现任何 URL 编码字符,那么您可以简单地阻止任何发送任何请求!例如,以下内容需要放在配置的顶部:

# Block any request that includes a %-encoded character in the query string
RewriteCond %{QUERY_STRING} %[\da-f]{2} [NC]
RewriteRule ^ - [R=400]

相关内容