我正在嘗試比較兩個伺服器變數作為 URL 重寫條件的一部分。但首先,一些背景......
在 IIS 中,如果您要求http://www.example.com/foo
並且foo
是目錄,IIS 會發送 302「物件已移動」重定向http://www.example.com/foo/
作為「禮貌重定向」(來源)。
如果您使用 IIS+ARR 作為具有 SSL 卸載的反向代理,則後端 IIS 節點接收的請求將透過 http 而不是 https。
將這兩種行為結合起來,IIS 的禮貌重定向就會刪除 SSL。禮貌重定向使用與 IIS 收到的請求相同的方案(來源),本例為 http 而非 https。
我想建立一個出站重寫規則,將傳入 URL 與傳出 Location 標頭進行比較,並將其從 http 重寫為 https,在本例中:
- 回應是重定向:
{RESPONSE_STATUS}
是 302 - 傳入請求透過 SSL:
{HTTPS}
“開啟” - 傳入的 URL 不以斜線結尾。
- 傳出的 Location 標頭以斜線結尾。
以上都是在前提條件下處理的。棘手的部分是最後一點:
- 傳出 Location 標頭的路徑與傳入 URL 相同,但附加了斜線。
下面是我到目前為止的程式碼。前提條件和標頭重寫都正常工作。但是,該條件會導致 500 錯誤(URL 重寫模組錯誤),大概是因為我{REQUEST_URI}
在模式中使用。我嘗試將條件分成兩個並使用捕獲組,但這也不起作用。有任何想法嗎?
<rule name="Fix: Courtesy Redirect + SSL Offloading = SSL dropped" preCondition="Courtesy Redirect Drops SSL" enabled="true">
<match serverVariable="RESPONSE_LOCATION" pattern="^http://(.+/)$" />
<conditions>
<add input="{RESPONSE_LOCATION}" pattern="{REQUEST_URI}/" />
</conditions>
<action type="Rewrite" value="https://{R:1}" />
</rule>
<preConditions>
<preCondition name="Courtesy Redirect Drops SSL">
<add input="{RESPONSE_STATUS}" pattern="^302$" />
<add input="{HTTPS}" pattern="^on$" />
<add input="{REQUEST_URI}" pattern=".*[^/]$" />
<add input="{RESPONSE_LOCATION}" pattern="^http://.+/$" />
</preCondition>
</preConditions>
答案1
您可以使用自訂重寫提供者。提供者是將一個字串轉換為另一個字串的 C# 程式碼。然後,您可以按照與使用重寫映射類似的方式使用它:
您可以選擇在 url 中根本無效的分隔符號。 (也許使用空格或類似的東西。我將使用它|
,以便它在本文中可見,但您應該選擇其他字串。)
您將編寫一條規則來設定伺服器變數的值IsItMatching
。伺服器變數的值將使用您的自訂 url 重寫提供者進行設定:
{provider_name:{server_variable_1}|{server_variable_2}}
然後,實作提供者的 C# 程式碼將執行此操作(偽代碼,無錯誤檢查):
string Rewrite(string input)
{
string[] inputVariables = input.split(separator);
if (inputVariables[0] == inputVariables[1] + "/")
return "yes";
else
return "no";
}
然後,您將再寫一條規則來檢查伺服器變數的值IsItMatching
是「yes」還是「no」。