使用應用程式閘道重寫 HTTP 標頭和 URL
應用程式閘道可讓您重寫所選的要求和回應內容。 您可以透過這項功能來轉譯 URL、查詢字串參數,以及修改要求和回應標頭。 您還可以新增條件,以確保僅在符合特定條件時,才重寫 URL 或指定的標頭。 這些條件所根據的是要求和回應資訊。
HTTP 標頭和 URL 重寫功能僅適用於 應用程式閘道 v2 SKU。
要求和回應標頭
應用程式閘道可讓您在要求和回應封包於用戶端與後端集區之間移動時,新增、移除或更新 HTTP 要求和回應標頭。 HTTP 標頭可讓用戶端和伺服器透過要求或回應傳遞其他資訊。 您可以重寫這些標頭來完成重要的工作,例如新增安全性相關的標頭欄位 (例如 HSTS/ X-XSS-Protection)、移除可能洩露敏感性資訊的回應標頭欄位,以及從 X-Forwarded-For 標頭中移除連接埠資訊。
您可以在要求和回應中重寫所有標頭,但、 和 Upgrade
標頭除外Connection
。 您也可以使用應用程式閘道來 建立自定義標頭 ,並將其新增至透過其路由傳送的要求和回應。 若要瞭解如何使用 Azure 入口網站與應用程式閘道重寫要求和回應標頭,請參閱這裡。
URL 路徑和查詢字串
應用程式閘道中的 URL 重寫功能可讓您:
重寫要求 URL 的主機名稱、路徑和查詢字串
選擇重寫接聽程式上所有要求的 URL,或僅重寫符合您所設定一或多個條件的要求。 這些條件以要求屬性為基礎 (要求標頭和伺服器變數)。
選擇根據原始 URL 或重寫的 URL 來路由傳送要求 (選取後端集區)
若要瞭解如何使用 Azure 入口網站與應用程式閘道重寫 URL,請參閱這裡。
瞭解 應用程式閘道 中的重寫
重寫集是路由規則、條件和動作的集合。
要求路由規則關聯: 重寫組態會透過其路由規則與來源接聽程式相關聯。 當您使用 Basic 類型的路由規則時,重寫組態會與其接聽程式相關聯,並做為全域重寫。 當您使用路徑型路由規則時,重寫組態會根據URL路徑對應來定義。 在後者的情況下,它只適用於網站的特定路徑區域。 您可以將重寫集套用至多個路由規則,但路由規則只能有一個與其相關聯的重寫。
重寫條件: 這是選擇性的設定。 根據您定義的條件,應用程式閘道 會評估 HTTP(S) 要求和回應的內容。 如果 HTTP(S) 要求或回應符合此條件,則會發生後續的「重寫動作」。 如果您將多個條件與某個動作產生關聯,則只有在符合所有條件時,才會執行此動作。 換句話說,它是邏輯 AND 作業。 您可以使用重寫條件來評估 HTTP(S) 要求和回應的內容。 此選擇性設定可讓您只在符合一或多個條件時執行重寫。 應用程式閘道使用這幾種變數來評估要求和回應的內容:
您可以選擇下列類型來尋找條件:
- HTTP 標頭 (要求和回應)
- 支援的 伺服器變數
Condition 可讓您透過文字或 Regex 模式來比對指定的標頭或變數是否存在。 針對進階重寫組態,您也可以擷取標頭或伺服器變數的值,以供稍後在 [重寫動作] 下使用。 深入瞭解 模式和擷取。
重寫動作: 重寫動作集可讓您重寫標頭(要求或回應)或 URL 元件。
動作可以有下列實值類型或其組合:
- Text (文字)。
- 要求標頭的值 - 若要使用擷取的要求標頭值,請將語法指定為
{http_req_headerName}
。 - 回應標頭的值 - 若要使用上述 Condition 中擷取的響應標頭值,請將語法指定為
{http_resp_headerName}
。 您可以從動作集的 「Set-Cookie」 回應標頭擷取值時使用{capt_header_value_matcher}
。 深入瞭解 [ 動作集] 底下的擷取。 - 伺服器變數 - 若要使用伺服器變數,請將語法指定為
{var_serverVariable}
。 支援的伺服器變數清單。
使用動作重寫 URL 時,支援下列作業:
- URL 路徑:要設定為路徑的新值。
- URL 查詢字串:必須重寫查詢字串的新值。
- 重新評估路徑對應:指定重寫之後,是否必須重新評估 URL 路徑對應。 如果保持未核取,則會使用原始 URL 路徑來比對 URL 路徑對應中的路徑模式。 如果設定為 true,則會重新評估 URL 路徑對應,以檢查是否符合重寫路徑。 啟用此參數有助於在重寫後將要求路由傳送至不同的後端集區。
模式比對和擷取
在 [條件] 和 [動作] 下支援 Patten 比對和擷取 (在 [動作] 下,它只支援特定標頭)。
模式比對
應用程式閘道 使用正則表達式進行模式比對。 撰寫模式比對語法時,您應該使用正則表示式 2 (RE2) 相容的運算式。
您可以在 [條件] 和 [動作] 下使用模式比對。
- 條件:這是用來比對標頭或伺服器變數的值。 若要比對 「Conditions」 下的模式,請使用 「pattern」 屬性。
- 動作:動作集下的模式比對僅適用於響應標頭 「Set-Cookie」。。 若要比對動作下 Set-Cookie 的模式,請使用 “HeaderValueMatcher” 屬性。 如果擷取,其值可以當做 {capt_header_value_matcher}使用。 由於可以有多個 Set-Cookie,此處的模式比對可讓您尋找特定的 Cookie。 範例:針對特定版本的使用者代理程式,您想要以 max-age=3600 (一小時)重寫 “cookie2” 的 set-cookie 回應標頭。 在此情況下,您可以使用
- 條件 - 類型:要求標頭、標頭名稱:使用者代理程式、比對模式:*2.0
- 動作 - 重寫類型:回應標頭、動作類型:Set、標頭名稱:Set-Cookie、標頭值比對器:cookie2=(.*),標頭值:cookie2={capt_header_value_matcher_1};Max-Age=3600
注意
如果您要使用核心規則集 3.1 或更早版本執行應用程式閘道 Web 應用程式防火牆 (WAF),則在使用與 Perl 相容的規則運算式 (PCRE) (英文) 時 (同時執行右合樣和左合樣 (負值或正值) 判斷提示) 可能會遇到問題。
擷取的語法
模式也可以用來擷取子字串以供稍後使用。 將括弧放在 regex 定義中的子模式周圍。 第一對括弧會將其子字串儲存在 1 中,而第二對會儲存在 2,以此類推。 您可以視需要使用多個括弧;Perl 只會持續定義更多編號的變數,讓您呈現這些擷取的字串。 您可以在此 Perl 程式設計指引中找到一些範例。
- (\d)(\d) # 比對兩位數字,將其擷取至群組 1 和 2
- (\d+) # 比對一或多個數字,將所有位數擷取至群組 1
- (\d+) # 比對一或多次,將最後一次擷取至群組 1
擷取之後,您可以使用下列格式在 [動作集] 值中使用它們:
- 對於要求標頭擷取,您必須使用 {HTTP_req_headerName_groupNumber}。 例如,{HTTP_req_User-Agent_1} 或 {HTTP_req_User-Agent_2}
- 對於回應標頭擷取,您必須使用 {HTTP_resp_headerName_groupNumber}。 例如,{http_resp_Location_1} 或 {http_resp_Location_2}。 對於透過 “HeaderValueMatcher” 屬性擷取的響應標頭 Set-Cookie,您必須使用 {capt_header_value_matcher_groupNumber}。 例如,{capt_header_value_matcher_1} 或 {capt_header_value_matcher_2}。
- 對於伺服器變數,您必須使用 {var_serverVariableName_groupNumber}。 例如,{var_uri_path_1} 或 {var_uri_path_2}
注意
- 使用 / 來前置詞和後綴模式不應在模式中指定以符合值。 例如,(\d)(\d) 會比對兩位數字。 /(\d)(\d)/ 不會比對兩位數字。
- 條件變數的大小寫必須符合擷取變數的大小寫。 例如,如果我的條件變數是 User-Agent,則我的擷取變數必須為 User-Agent (也就是 {HTTP_req_User-Agent_2})。 如果我的條件變數定義為 user-agent,則我的擷取變數必須為 user-agent (也就是 {HTTP_req_user-agent_2})。
- 如果您想要使用整個值,則不應該提及數字。 單純使用 {HTTP_req_headerName} 格式之類,而不使用 groupNumber。
伺服器變數
應用程式閘道會使用伺服器變數來儲存伺服器、與用戶端的連線,以及連線上目前要求的相關實用資訊。 儲存的資訊範例包括用戶端的 IP 位址和網頁瀏覽器類型。 例如,當新頁面載入或張貼表單時,伺服器變數會動態地變更。 您可以使用這些變數來評估重寫條件和重寫標頭。 若要使用伺服器變數的值來重寫標頭,您必須在語法 {var_serverVariableName} 中指定這些變數
應用程式閘道支援下列伺服器變數:
變數名稱 | 描述 |
---|---|
add_x_forwarded_for_proxy | 以 IP1、IP2、IP3 等格式附加 client_ip 變數的 X-Forwarded-For 用戶端要求標頭欄位 (請參閱下表稍後的說明)。 如果 X-Forwarded-For 欄位不在用戶端要求標頭中,則 add_x_forwarded_for_proxy 變數等於 $client_ip 變數。 當您想要重寫應用程式閘道設定的 X-Forwarded-For header 標頭時,此變數會很有用,如此可讓標頭只包含 IP 位址,而不包含連接埠資訊。 |
ciphers_supported | 用戶端支援的加密清單。 |
ciphers_used | 用於所建立 TLS 連線的加密字串。 |
client_ip | 應用程式閘道接收要求所在用戶端的 IP 位址。 如果應用程式閘道和原始用戶端之前有反向 Proxy,client_ip 會傳回反向 Proxy 的 IP 位址。 |
client_port | 用戶端連接埠。 |
client_tcp_rtt | 用戶端 TCP 連線的相關資訊。 適用於支援 TCP_INFO 通訊端選項的系統。 |
client_user | 使用 HTTP 驗證時,提供用於驗證的使用者名稱。 |
host | 優先順序如下:來自要求行的主機名稱、來自 Host 要求標頭欄位的主機名稱,或是與要求相符的伺服器名稱。 範例:在要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam 中,主機值為 contoso.com |
cookie_name | name Cookie。 |
http_method | 用來提出 URL 要求的方法。 例如,GET 或 POST。 |
http_status | 工作階段狀態。 例如,200、400 或 403。 |
http_version | 要求通訊協定。 通常是 HTTP/1.0、HTTP/1.1 或 HTTP/2.0。 |
query_string | 接在所要求 URL 中「?」後面的變數/值組清單。 範例:在要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam 中,query_string 值為 id=123&title=fabrikam |
received_bytes | 要求的長度 (包括要求行、標頭和要求本文)。 |
request_query | 要求行中的引數。 |
request_scheme | 要求結構配置:http 或 https。 |
request_uri | 完整的原始要求 URI (含引數)。 範例:在要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam* 中,request_uri 值為 /article.aspx?id=123&title=fabrikam |
sent_bytes | 傳送給用戶端的位元組數。 |
server_port | 已接受要求的伺服器連接埠。 |
ssl_connection_protocol | 所建立 TLS 連線的通訊協定。 |
ssl_enabled | 如果連線以 TLS 模式運作,則為「On」。 否則便為空字串。 |
uri_path | 識別 Web 用戶端想要存取主機中的特定資源。 變數是指任何操作之前的原始 URL 路徑。 這是要求 URI 中不含引數的部分。 例如,在要求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam 中,uri_path值為 /article.aspx 。 |
相互驗證伺服器變數
應用程式閘道支援下列用於相互驗證案例的伺服器變數。 使用這些伺服器變數的方式與其他伺服器變數相同。
變數名稱 | 描述 |
---|---|
client_certificate | 用於已建立 SSL 連線的 PEM 格式用戶端憑證。 |
client_certificate_end_date | 用戶端憑證的結束日期。 |
client_certificate_fingerprint | 用於已建立 SSL 連線的用戶端憑證 SHA1 指紋。 |
client_certificate_issuer | 用於已建立 SSL 連線的用戶端憑證「issuer DN」字串。 |
client_certificate_serial | 用於已建立 SSL 連線的用戶端憑證序號。 |
client_certificate_start_date | 用戶端憑證的開始日期。 |
client_certificate_subject | 用於已建立 SSL 連線的用戶端憑證「subject DN」字串。 |
client_certificate_verification | 用戶端憑證驗證的結果:「成功」、「失敗:<原因>」,或如果憑證不存在,則為「無」。 |
標頭重寫的常見案例
從 X-Forwarded-For 標頭中移除連接埠資訊
應用程式閘道會將 X-Forwarded-For 標頭插入所有要求,再將要求轉送至後端。 此標頭是以逗號分隔的 IP 連接埠清單。 在某些情況下,後端伺服器只需要標頭來包含 IP 位址。 您可以使用標頭重寫,以從 X-Forwarded-For 標頭中移除連接埠資訊。 其中一種方法是將標頭設定為 add_x_forwarded_for_proxy 伺服器變數。 或者,您也可以使用變數 client_ip:
修改重新導向 URL
在某些情況下,重新導向 URL 的修改可能會很有用。 例如:用戶端原本已重新導向至「/blog」之類的路徑,但現在應該因為內容結構的變更而傳送至「/updates」。
警告
有時候,修改重新導向 URL 的需求會出現在設定的內容中,其中應用程式閘道設定為覆寫後端的主機名稱。 後端所見的主機名稱與瀏覽器所見的主機名稱不同。 在此情況下,重新導向不會使用正確的主機名稱。 我們不建議這種設定。
此類設定的限制和影響如在反向 Proxy 及其後端 Web 應用程式之間保留原始 HTTP 主機名稱中所述。 App Service 的建議設定是遵循使用應用程式閘道設定 App Service 中的「自訂網域 (建議)」指示。 如下列範例所述,重寫回應上的位置標頭應該視為因應措施,而且無法解決根本原因。
當 App Service 傳送重新導向回應時,會在其回應的位置標頭中使用與其從應用程式閘道所接收要求中主機名稱相同的主機名稱。 因此,用戶端會直接對 contoso.azurewebsites.net/path2
提出要求,而非透過應用程式閘道 (contoso.com/path2
)。 不需要略過應用程式閘道。
您可以將位置標頭中的主機名稱設定為應用程式閘道的網域名稱,以解決此問題。
以下是取代主機名稱的步驟:
使用條件建立重寫規則,以評估回應中的位置標頭是否包含 azurewebsites.net。 輸入模式
(https?):\/\/.*azurewebsites\.net(.*)$
。執行動作來重寫位置標頭,使其具有應用程式閘道的主機名稱。 輸入
{http_resp_Location_1}://contoso.com{http_resp_Location_2}
作為標頭值來執行此動作。 或者,您也可以使用伺服器變數host
來設定主機名稱以符合原始要求。
實作安全性 HTTP 標頭以防止弱點
您可以在應用程式回應中實作必要的標頭,以修正數個安全性弱點。 這些安全性標頭包括 X-XSS-Protection、Strict-Transport-Security 和 Content-Security-Policy。 您可以使用應用程式閘道來設定所有回應的這些標頭。
刪除不必要的標頭
您可能想要從 HTTP 回應中移除顯示敏感性資訊的標頭。 例如,您可能想要移除後端伺服器名稱、作業系統或程式庫詳細資料等資訊。 您可以使用應用程式閘道來移除這些標頭:
無法建立重寫規則來刪除主機標頭。 如果您嘗試建立重寫規則,並將動作類型設定為 delete,且將標頭設定為 host,則會產生錯誤。
檢查標頭是否存在
您可以評估 HTTP 要求或回應標頭,以瞭解標頭或伺服器變數是否存在。 您想要僅在特定標頭存在才執行標頭重寫時,此評估相當實用。
URL 重寫的常見案例
參數型路徑選取
若要完成您想要根據標頭、URL 部分或要求中查詢字串的值來選擇後端集區的案例,您可以使用 URL 重寫功能和路徑型路由的組合。
若要這樣做,請使用檢查特定參數的條件來建立重寫集 (查詢字串、標頭等),然後執行變更 URL 路徑的動作 (請確定重新評估路徑對應已啟用)。 接著,重寫集必須與路徑型規則相關聯。 路徑型規則必須包含重寫集及其對應後端集區中指定的相同 URL 路徑。
因此,重寫集可讓使用者檢查特定參數並指派新路徑給它,而路徑型規則可讓使用者將後端集區指派給這些路徑。 只要啟用「重新評估路徑對應」,流量就會根據重寫集中指定的路徑路由。
如需使用查詢字串的使用案例範例,請參閱在入口網站中使用參數型路徑選取項目來路由流量。
根據 URL 重寫查詢字串參數
請考慮購物網站的案例,其中使用者可見連結應該是簡單易懂的,但後端伺服器需要查詢字串參數來顯示正確的內容。
在此情況下,應用程式閘道可以從 URL 擷取參數,並從 URL 新增查詢字串索引鍵/值組。 例如,假設使用者想要從 https://www.contoso.com/fashion/shirts
重寫至 https://www.contoso.com/buy.aspx?category=fashion&product=shirts
,則可以透過下列 URL 重寫設定來達成。
條件 - 如果伺服器變數 uri_path
等於模式 /(.+)/(.+)
動作 - 將 URL 路徑設定為 buy.aspx
,並將查詢字串設定為 category={var_uri_path_1}&product={var_uri_path_2}
如需達成上述案例的逐步指南,請參閱使用 Azure 入口網站與應用程式閘道重寫 URL
重寫設定的常見陷阱
基本要求路由規則不允許啟用「重新評估路徑對應」。 這是為了避免基本路由規則的無限評估迴圈。
必須至少有 1 個條件式重寫規則,或 1 個重寫規則未針對路徑型路由規則啟用「重新評估路徑對應」,以防止路徑型路由規則的無限評估迴圈。
如果根據用戶端輸入動態建立迴圈,傳入要求會以 500 錯誤碼終止。 應用程式閘道會繼續提供其他要求,而不會在此類案例中降級。
使用 URL 重寫或主機標頭重寫搭配 Web 應用程式防火牆 (WAF_v2 SKU)
當您設定 URL 重寫或主機標頭重寫時,WAF 評估會在修改要求標頭或 URL 參數之後 (重寫後) 發生。 當您移除應用程式閘道上的 URL 重寫或主機標頭重寫設定時,WAF 評估會在標頭重寫 (重寫前) 之前完成。 此順序可確保 WAF 規則會套用至後端集區所接收的最終要求。
例如,假設您有標頭 "Accept" : "text/html"
的下列標頭重寫規則 - 如果標頭 "Accept"
的值等於 "text/html"
,請將值重寫為 "image/png"
。
在這裡,只有已設定的標頭重寫,WAF 評估將會在 "Accept" : "text/html"
上完成。 但是當您設定 URL 重寫或主機標頭重寫時,WAF 評估會在 "Accept" : "image/png"
上完成。
URL 重寫與 URL 重新導向
針對 URL 重寫,應用程式閘道會在要求傳送至後端之前重寫 URL。 這不會變更使用者在瀏覽器中看到的內容,因為變更會向使用者隱藏。
針對 URL 重新導向,應用程式閘道會使用新的 URL 將重新導向回應傳送至用戶端。 接著,用戶端必須將其要求重新傳送至重新導向中提供的新 URL。 使用者在瀏覽器中看到的 URL 會更新為新的 URL。
限制
- 當應用程式閘道設定為重新導向要求或顯示自訂錯誤頁面時,不支援重寫。
- 要求標頭名稱可以包含英數字元和連字號。 當要求傳送至後端目標時,將會捨棄包含其他字元的標頭名稱。
- 回應標頭名稱可以包含任何英數字元和 RFC 7230 (英文) 中所定義的特定符號。
- 無法重寫連線和升級標頭
- 重寫不支援直接從應用程式閘道產生的 4xx 和 5xx 回應