Dot-Htaccess

我應該在 RewriteCond 中轉義斜杠“/”嗎?

  • November 11, 2021

我是否需要在 RewriteCond 中轉義斜杠“/”?

目前我在.htaccess中寫了以下規則:

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

但是,這僅適用於https://www.datanumen.com/fi/customer/index.php?rp=/knowledgebase/7/How-to-order-the-full-version-of-DataNumen-Access之類的 URL -Repair.html&language=swedish,但不適用於https://www.datanumen.com/fi/customer/index.php?rp=%2Fknowledgebase%2F7%2FHow-to-order-the-full-version-之類的 URL 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

我應該逃避斜線/RewriteCond

通過“轉義斜杠”,您的真正意思是“我應該匹配 URL 編碼的斜杠嗎?”。這完全取決於向您的伺服器發出的 HTTP 請求。

但是我檢查了https://serverfault.com/a/968916/280923,它說“/不需要轉義斜杠 ( )”。所以我很困惑。

連結的問題/答案與目前問題無關。該問題是處理 Apache 指令/正則表達式中的反斜杠轉義,而不是您在此處處理的 URL 編碼(或 % 編碼)URL。這是用於不同目的的兩種非常不同類型的“轉義”方法。

您正在處理的是 % 編碼的 URL。URL 在 HTTP 請求中的顯示方式。URL 的不同部分(特別是“路徑”和“查詢字元串”)具有不同的編碼要求。是否需要對特定字元進行 % 編碼取決於它在該上下文中是否具有特殊含義。

正如RFC3986中定義的那樣,斜杠 ( /) 並不嚴格需要在 URL 的查詢字元串部分進行 % 編碼。但是,URL 編碼函式(例如 PHP 和 JavaScript)通常會對該字元進行 %-encode。(我認為這在很大程度上是歷史性的,因為據報導一些舊的實現沒有正確處理未編碼的斜線 - 參考RFC3986。)

但是,無論一個字元是否需要進行 URL 編碼(以否定其特殊含義),任何字元都可以進行 % 編碼,這應該與文字(未編碼)字元一樣對待。

您是否需要匹配/(解碼)或%2F(編碼)取決於該字元是否在請求中進行了 % 編碼。

您的問題是QUERY_STRINGserver 變數沒有 %-decoded,這與RewriteRule pattern匹配的 URL-path 不同。

但是……你需要檢查 %-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但是,這並不能真正幫助您,因為它不會 %-decode 斜杠,即。%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]

引用自:https://serverfault.com/questions/1083215