你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

使用应用程序网关重写 HTTP 标头和 URL

应用程序网关允许在请求和响应中重写所选内容。 借助此功能,可以转换 URL、查询字符串参数,以及修改请求和响应标头。 还可以添加条件,以确保仅在满足某些条件时重写 URL 或指定的标头。 这些条件以请求和响应信息为基础。

HTTP 标头和 URL 重写功能仅适用于应用程序网关 v2 SKU

请求和响应头

当请求和响应数据包在客户端与后端池之间移动时,可以通过应用程序网关添加、移除或更新 HTTP 请求和响应标头。 HTTP 标头允许客户端和服务器通过请求或响应传递额外信息。 通过重写这些标头,可以完成重要任务,包括:

  • 添加与安全相关的标头字段,例如 HSTS 和 X-XSS-Protection
  • 删除可能会显示敏感信息的响应标头字段
  • 从 X-Forwarded-For 标头中删除端口信息

可以重写请求和响应中的所有标头,但 ConnectionUpgrade 标头除外。 还可以使用应用程序网关创建自定义标头,并将其添加到通过该网关路由的请求和响应。 若要了解如何使用 Azure 门户通过应用程序网关重写请求和响应标头,请参阅 此处

显示请求和响应数据包中的标头的关系图。

URL 路径和查询字符串

利用应用程序网关中的 URL 重写功能,你可以:

  • 重写请求 URL 的主机名、路径和查询字符串

  • 选择重写侦听器上所有请求的 URL,或者只重写与所设置的一个或多个条件匹配的要求的 URL。 这些条件基于请求属性(请求头和服务器变量)。

  • 选择基于原始 URL 或重写的 URL 来路由请求(选择后端池)

若要了解如何使用 Azure 门户重写应用程序网关的 URL,请参阅 此处

此图描述了使用应用程序网关重写 URL 的过程。

了解应用程序网关中的重写

重写规则集是路由规则、条件和操作的集合。

  • 请求路由规则关联: 重写配置通过其路由规则与源监听器关联。 使用 Basic 类型的路由规则时,重写配置会与其侦听器关联,并充当全局重写。 使用基于路径的路由规则时,根据 URL 路径映射定义重写配置。 在后一种情况下,该规则只会应用于站点的特定路径区域。 可以将重写集应用于多个路由规则,但路由规则只能有一个与之关联的重写。

  • 重写条件: 此配置是可选的。 根据定义的条件,应用程序网关评估 HTTP(S) 请求和响应的内容。 如果 HTTP(S) 请求或响应与此条件匹配,则会发生后续的“重写作”。 如果将多个条件关联到一个操作,仅当满足所有条件时,才会发生该操作。 换句话说,它是一个逻辑与操作。 可以使用重写条件评估 HTTP 请求和响应的内容。 此可选配置允许仅在满足一个或多个条件时执行重写。 应用程序网关使用以下类型的变量来评估请求和响应的内容:

    可以选择以下类型来查找条件:

    条件允许你通过文本或正则表达式模式匹配指定的标头或变量是否存在。 对于高级重写配置,还可以捕获标头或服务器变量的值,供稍后在重写操作中使用。 详细了解 模式和捕获

  • 重写操作: 重写操作集允许重写请求或响应的标头或 URL 组件。

    操作可以使用以下值类型或其组合:

    • Text。
    • 请求标头的值 - 若要使用捕获的请求标头的值,请将语法指定为 {http_req_headerName}
    • 响应标头的值 - 若要使用上述条件中捕获的响应标头的值,请将语法指定为 {http_resp_headerName}。 “重写操作”块还支持 Set-Cookie 标头的“标头值匹配程序”字段。 此可选字段允许在存在多个同名的 Set-Cookie 标头时匹配和捕获特定标头的值。 若要操作该特定 Cookie 的捕获值,可使用 {capt_header_value_matcher}。 详细了解 动作集下的捕获
    • 服务器变量 - 要使用服务器变量,请将语法指定为 {var_serverVariable}支持的服务器变量列表

注意

当前不支持通过门户使用标头值匹配器字段 {capt_header_value_matcher}。 因此,如果使用此字段,您需要在执行任何 PUT 操作时使用非门户途径。

当您使用操作重写 URL 时,支持以下操作:

  • URL 路径:要设置为路径的新值。
  • URL 查询字符串:必须将查询字符串重写到的新值。
  • 重新评估路径映射:指定重写后是否必须重新评估 URL 路径映射。 如果未选中此选项,则原始 URL 路径用于匹配 URL 路径映射中的路径模式。 如果将此选项设置为 true,则会重新评估 URL 路径映射,以检查与重写路径的匹配项。 启用此开关有助于在重写后将请求路由到不同的后端池。

模式匹配和捕获

应用程序网关支持在条件和动作下进行模式匹配和捕获。 在“操作”下,它仅支持对特定标头的模式匹配和捕获。

模式匹配

应用程序网关使用正则表达式进行模式匹配。 编写模式匹配语法时,请使用正则表达式 2 (RE2) 兼容的表达式。

可以在条件和操作下使用模式匹配。

  • 条件:使用此设置匹配标头或服务器变量的值。 若要匹配“条件”下的模式,请使用“pattern”属性。
  • :作集下的模式匹配仅适用于响应标头 Set-Cookie。 若要在某个动作下匹配模式 Set-Cookie,请使用 HeaderValueMatcher 属性。 如果捕获,则可以将其值用作 {capt_header_value_matcher}。 由于可能存在多个Set-Cookie标头,此模式匹配使你可以查找特定的Cookie。 例如,对于特定版本的用户代理,你想要用max-age=3600(一小时)重写set-cookie的响应标头cookie2。 在本例中,可以使用
    • 条件 - 类型:请求标头,标头名称:user-agent,要匹配的模式:*2.0
    • Action - 重写类型:响应标头,操作类型:Set,标头名称:Set-Cookie,标头值匹配:cookie2=(.*),标头值:cookie2={capt_header_value_matcher_1};Max-Age=3600

注意

如果运行具有核心规则集 3.1 或更早版本的应用程序网关 Web 应用程序防火墙(WAF),则在执行 lookahead 和 lookbehind(负或正)断言时,使用 Perl 兼容正则表达式(PCRE)时可能会遇到问题。

捕获语法

可以使用模式捕获子字符串供以后使用。 请在正则表达式定义中的子模式两侧加上括号。 第一对括号将其子字符串存储在 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})。 如果条件变量定义为用户代理,则我的捕获变量必须为用户代理(即 {http_req_user-agent_2})。
  • 如果要使用整个值,则不应提及数字。 直接使用 {http_req_headerName} 之类的格式,不带 groupNumber。

服务器变量

应用程序网关使用服务器变量来存储有关服务器、与客户端建立的连接以及对连接的当前请求的有用信息。 例如,存储的信息包括客户端的 IP 地址和 Web 浏览器类型。 服务器变量会动态更改,例如,加载新页或发布表单时就会更改。 可以使用这些变量来评估重写条件和重写标头。 若要使用服务器变量的值重写标头,需要在语法 {var_serverVariableName} 中指定这些变量

应用程序网关支持以下服务器变量:

变量名称 说明
add_x_forwarded_for_proxy X-Forwarded-For 客户端请求标头字段,其中追加了 IP1、IP2、IP3 等格式的 client_ip 变量(请参阅此表后面的解释)。 如果 X-Forwarded-For 字段不在客户端请求标头中,则 add_x_forwarded_for_proxy 变量等于 $client_ip 变量。 若要重写由应用程序网关设置的 X-Forwarded-For 标头,使该标头仅包含 IP 地址而不包含端口信息,则此变量很有用。
支持的密码 客户端支持的加密法列表。
使用的密码 用于已建立 TLS 连接的加密法字符串。
客户端IP地址 客户端的 IP 地址,应用程序网关从中接收请求。 如果应用程序网关和发起方客户端的前面有反向代理,则 client_ip 会返回该反向代理的 IP 地址。
客户端端口 客户端端口。
client_tcp_rtt 有关客户端 TCP 连接的信息。 在支持 TCP_INFO 套接字选项的系统上可用。
客户端用户 使用 HTTP 身份验证时提供用于身份验证的用户名。
主持人 按此优先顺序排列:请求行中的主机名、Host 请求标头字段中的主机名,或与请求匹配的服务器名称。 示例:在请求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam 中,主机值为 contoso.com
cookie_name name Cookie。
HTTP方法 用于发出 URL 请求的方法。 例如 GET 或 POST。
HTTP状态 会话状态。 例如 200、400 或 403。
HTTP版本 请求协议。 通常为 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连接协议 已建立的 TLS 连接的协议。
SSL已启用 如果连接在 TLS 模式下建立,则为“On”。 否则为空字符串。
uri_path 标识 Web 客户端要访问的主机中的特定资源。 变量指代在任何操作之前的原始 URL 路径。 这是请求 URI 中没有参数的部分。 例如,在请求 http://contoso.com:8080/article.aspx?id=123&title=fabrikam 中,uri_path 值为 /article.aspx

相互身份验证服务器变量

应用程序网关支持以下用于相互身份验证方案的服务器变量。 像使用其他服务器变量一样使用这些服务器变量。

变量名称 说明
客户端证书 已建立的 SSL 连接的客户端证书,采用 PEM 格式。
客户证书终止日期 客户端证书的结束日期。
client_certificate_fingerprint 已建立的 SSL 连接的客户端证书的 SHA1 指纹。
client_certificate_issuer 已建立的 SSL 连接的客户端证书的“颁发者 DN”字符串。
client_certificate_serial 已建立的 SSL 连接的客户端证书的序列号。
客户证书开始日期 客户端证书的开始日期。
client_certificate_subject 已建立的 SSL 连接的客户端证书的“使用者 DN”字符串。
客户端证书验证 客户端证书验证的结果: 成功FAILED:<reason>NONE (如果证书不存在)。

标头重写的常见方案

从 X-Forwarded-For 标头中删除端口信息

应用程序网关先在所有请求中插入 X-Forwarded-For 标头,然后将请求转发到后端。 此标头是 IP 端口的逗号分隔列表。 在某些情况下,后端服务器只需在标头中包含 IP 地址。 你可以使用标头重写从 X-Forwarded-For 标头中删除端口信息。 若要这样做,一种做法是将该标头设置为 add_x_forwarded_for_proxy 服务器变量。 此外,也可使用变量 client_ip:

显示删除端口操作的屏幕截图。

修改重定向 URL

在某些情况下,修改重定向 URL 可能很有用。 例如,由于内容结构的变化,你最初可能会将客户端重定向到“/blog”之类的路径,但现在想要将它们发送到“/更新”。

警告

配置应用程序网关以覆盖后端的主机名时,可能需要修改重定向 URL。 在此配置中,后端看到不同于浏览器的主机名。 重定向不使用正确的主机名。 不建议使用此配置。

有关此类配置的限制和影响的详细信息,请参阅 保留反向代理与其后端 Web 应用程序之间的原始 HTTP 主机名。 有关应用服务的建议设置,请参阅使用应用程序网关配置应用服务中的“自定义域(推荐)”。 应将重写响应中的位置标头视为一种解决方法,这如以下示例中所述,但这并不能解决根本原因。

当应用服务发送重定向响应时,它会在其响应的位置标头中,使用它从应用程序网关收到的请求中的相同主机名。 因此,客户端会直接向 contoso.azurewebsites.net/path2 发出请求,而不是通过应用程序网关 (contoso.com/path2) 发出请求。 不应该绕过应用程序网关。

将 location 标头中的主机名设置为应用程序网关的域名即可解决此问题。

下面是替换主机名的步骤:

  1. 创建一个重写规则,其中包含一个条件,用于检查响应中的位置标头是否包含 azurewebsites.net。 输入模式 `(https?)://azurewebsites.net`。

  2. 执行相应的操作来重写 location 标头,使其包含应用程序网关的主机名。 输入 {http_resp_Location_1}://contoso.com{http_resp_Location_2} 为标头值。 此外,也可使用服务器变量 host 将主机名设置为与原始请求匹配。

    屏幕截图显示了修改位置标头操作。

实现安全 HTTP 标头以防止漏洞

在应用程序响应中实现必要的标头可以修复多个安全漏洞。 这些安全标头包括 X-XSS-Protection、Strict-Transport-Security 和 Content-Security-Policy。 可以使用应用程序网关为所有响应设置这些标头。

安全性标头的屏幕截图。

删除不需要的标头

你可能想要从 HTTP 响应中删除透露敏感信息的标头。 例如,你可能想要移除后端服务器名称、操作系统或库详细信息等信息。 可以使用应用程序网关删除以下标头:

显示删除标头操作的屏幕截图。

无法创建重写规则来删除主机标头。 如果尝试创建重写规则,将该规则的操作类型设置为删除,并将标头设置为主机,则会导致错误。

检查某个标头是否存在

可以在 HTTP 请求或响应标头中评估某个标头或服务器变量是否存在。 如果你希望只有存在特定的标头时执行标头重写,则此评估非常有用。

显示标头操作的检查状态的屏幕截图。

URL 重写的常见方案

根据参数选择路径

若要完成想要根据标头值、URL 部分或请求中的查询字符串选择后端池的方案,请使用 URL 重写功能和基于路径的路由的组合。

使用检查特定参数(查询字符串、标头等)的条件创建重写集,然后执行更改 URL 路径的作(确保启用 重新评估路径映射 )。 将重写集关联到基于路径的规则。 基于路径的规则必须包含重写集中指定的相同 URL 路径及其相应的后端池。

因此,重写集允许检查特定参数并为其分配新路径,并且基于路径的规则允许向这些路径分配后端池。 只要启用了“重新评估路径映射”,路径流量的路由将基于重写集中指定的路径。

有关使用查询字符串的用例示例,请参阅在门户中使用基于参数的路径选择来路由流量

基于 URL 重写查询字符串参数

假设购物网站的用户可见链接简单易懂,但后端服务器需要查询字符串参数来显示正确的内容。

在这种情况下,应用程序网关可以从 URL 捕获参数,并从 URL 中的这些参数添加查询字符串键值对。 例如,如果用户要重写 https://www.contoso.com/fashion/shirtshttps://www.contoso.com/buy.aspx?category=fashion&product=shirts此目标,可以通过以下 URL 重写配置来实现此目标。

条件 - 如果服务器变量 uri_path 等于模式 /(.+)/(.+)

URL 重写方案 2-1。

操作 - 将 URL 路径设置为 buy.aspx,将查询字符串设置为 category={var_uri_path_1}&product={var_uri_path_2}

URL 重写方案 2-2。

有关实现前面所述的方案的分步指南,请参阅 使用 Azure 门户通过应用程序网关重写 URL

重写配置常见缺陷

  • 无法为基本请求路由规则启用“重新评估路径映射”。 此限制可防止基本路由规则的无限计算循环。

  • 对于基于路径的路由规则,至少需要一个条件重写规则或一个未启用“重新评估路径映射”的重写规则。 此要求可防止基于路径的路由规则的无限评估循环。

  • 如果根据客户端输入动态创建循环,传入的请求将终止并显示 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 中定义的特定符号。
  • 不能重写X-Original-HostConnectionupgrade标头。
  • 直接从应用程序网关生成的 4xx 和 5xx 响应不支持重写。

后续步骤