URL 重写模块 2.0 配置参考

作者:Ruslan Yakushev

本文档的此部分适用于 IIS 7 的 URL 重写模块版本 2.0

本文概述了 URL 重写模块 2.0 功能,并介绍了此版本中使用的新配置概念。 有关 URL 重写模块 1.1 配置的详细信息,请参阅 URL 重写模块配置参考

目录

功能概述

适用于 IIS 的 Microsoft URL 重写模块 2.0 是一个增量版本,其中包含版本 1.1 中的所有功能,并添加了对响应标头和内容重写的支持。 该模块将正则表达式或野生卡模式应用于 HTTP 响应,以基于出站重写规则表示的重写逻辑查找和替换内容部件。 更具体地说,该模块可用于:

  • 将响应 HTML 中 Web 应用程序生成的 URL 替换为更用户友好且搜索引擎友好的等效 URL。
  • 修改由反向代理后面的 Web 应用程序生成的 HTML 标记中的链接。
  • 修改现有响应并设置新的响应 HTTP 标头。
  • 修复任何 HTTP 响应的内容,包括 JavaScript、CSS、RSS 等。

警告

当响应头或响应内容被出站重写规则修改时,应格外小心,以确保插入响应中的文本不包含任何客户端可执行代码,否则可能会导致跨站点脚本漏洞。 当重写规则使用不受信任的数据(例如 HTTP 标头或查询字符串)来生成要插入到 HTTP 响应中的字符串时,这一点尤其重要。 在这种情况下,替换字符串应使用 HtmlEncode 函数进行 HTML 编码,例如:

<action type="Rewrite" value="{HtmlEncode:{HTTP_REFERER}}" />

出站规则概述

用于响应重写的主要配置概念是出站规则的概念。 出站规则用于表达要比较或匹配响应内容的逻辑,以及如果比较成功,该怎么办。

从概念上讲,出站规则包含以下部分:

  • 先决条件 - 可选先决条件用于在开始任何规则评估之前检查请求元数据。 先决条件可能包含针对请求元数据的多个条件检查,并且可用于筛选出不应重写的响应,例如图像或视频文件。
  • 标记筛选器 - 标记筛选器 用于缩小响应中对一组已知或自定义标记的搜索范围。 使用标记筛选器时,指定的标记的内容仅与规则模式匹配,而不是将整个响应内容与模式匹配。
  • 模式 – 规则模式用于指定正则表达式或野生卡模式,该模式将用于在响应内容中进行搜索。
  • 条件 – 可选条件集合用于指定在响应内容中找到模式匹配项时要执行的附加逻辑操作。 在条件中,可以为 HTTP 标头或服务器变量的某些值检查。
  • 操作 – 操作用于指定在找到模式匹配项并成功评估所有规则条件时要执行的操作。

规则执行

执行出站规则的过程不同于用于入站规则的过程。 每个请求只评估一次入站规则集,因为它的输入只是单个请求 URL 字符串。 每个响应可能会评估出站规则集多次,因为它正在 HTTP 响应内容中的多个位置应用。 例如,如果有规则集,如下所示:

规则 1:适用于<>标记和 <img> 标记

规则 2:适用于<>标记

和 HTML 响应包含以下标记:

<a href="/default.aspx"><img src="/logo.jpg" />Home Page</a>

然后,URL 重写模块 2.0 将针对“/default.aspx”字符串评估规则 1。 如果规则已成功执行,则规则 1 的输出将提供给 Rule2。 如果成功执行规则 2,则规则 2 的输出将用于替换响应中标记中的 <> href 属性的内容。

之后,URL 重写模块 2.0 将针对“/logo.jpg”字符串评估 Rule1。 如果规则成功执行,则其输出将用于替换响应中 img> 标记中的 <src 属性的内容。

规则继承

如果规则在多个配置级别上定义,则 URL 重写模块将评估包含父配置级别的分布式规则的规则集以及当前配置级别的规则。 计算以父到子顺序执行,这意味着先计算父规则,最后一个子级别上定义的规则将最后计算。

出站规则配置

先决条件集合

如果应根据响应内容评估规则,则使用先决条件检查。 预条件集合在 preConditions> 节中<定义为命名集合,它可能包含一个或多个预条件检查。 出站规则按名称引用条件集合。

先决条件集合具有一个名为 logicalGrouping 的属性,用于控制条件的计算方式。 如果满足以下条件,则先决条件集合的计算结果为 true:

  • 如果 使用了 logicalGrouping=“MatchAll” ,则所有先决条件的计算结果为 true。
  • 如果 使用了 logicalGrouping=“MatchAny” ,则至少有一个预条件的计算结果为 true。

通过指定以下属性来定义先决条件:

  • 输入字符串 - 预条件输入指定要用作条件评估输入的项。 预条件输入是一个任意字符串,可以包括服务器变量和先前条件模式的后退引用。
  • 模式 - 可以使用正则表达式语法或使用 wild卡 语法来指定预条件模式。 在预条件中使用的模式类型取决于为预条件集合定义的 patternSyntax 标志的值

此外,可以使用求反特性来否定预条件评估的结果。

如果响应内容类型为 text/html,则检查的先决条件示例:

<preConditions>
    <preCondition name="IsHTML">
        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
    </preCondition>
</preConditions>

标记筛选器

标记筛选器用于将响应内容中的搜索范围缩小到一组已知或自定义的 HTML 标记。 当重写规则使用标记筛选器时,URL 重写模块 2.0 会查找规则标记筛选器中列出的 HTML 标记,然后获取该标记的 URL 属性的内容,并针对规则的模式对其进行评估,而不是匹配整个响应的规则模式。 标记筛选器在出站规则的 match> 元素的 <filterByTags 属性内指定。 例如:

<match filterByTags="A" pattern="^/(article\.aspx.*)" />

如果 HTTP 响应包含定位标记,例如:

<a href="/article.aspx?id=1">link</a>

然后,将针对字符串评估重写规则模式:“/article.aspx?id=1”。

预定义标记

URL 重写模块 2.0 包括一组可用于出站规则的预定义标记。 下表列出了所有预定义标记和属性,其值将用作出站规则模式的输入:

标记 特性
A href
区域 href
Base href
窗体 action
Frame src,longdesc
个人资料
IFrame src,longdesc
图像 src, longdesc, usemap
输入 src,usemap
链接。 href
脚本 src

自定义标记

如果需要在预定义标记集合中包含的标记的属性内执行重写,则可以使用自定义标记集合来指定标记名称和需要重写的相应属性。 自定义标记集合定义为 customTags> 节中的<命名集合。 出站规则按名称引用自定义标记集合。

以下示例演示自定义标记集合的定义:

<customTags>
    <tags name="My Tags">
        <tag name="item" attribute="src" />
        <tag name="element" attribute="src" />
    </tags>
</customTags>

可以从出站规则引用此自定义标记集合,如以下示例所示:

<match filterByTags="A, CustomTags" customTags="My Tags" pattern="^/(article\.aspx.*)" />

规则模式

规则模式用于指定规则输入字符串应匹配的内容。 规则输入因规则配置而异:

  • 如果规则使用标记筛选器,则匹配标记属性的内容将作为模式匹配的输入传递。
  • 如果规则不使用任何标记筛选器,则整个响应内容将作为模式匹配的输入传递。

模式是在重写规则的匹配>元素内<指定的。

完整响应模式匹配

如果未 在规则的匹配元素中指定 filterByTags 属性,则模式将应用于整个响应内容。 对整个响应内容的正则表达式模式的计算是 CPU 密集型操作,可能会影响 Web 应用程序的性能。 有多种选项可以降低完整响应模式匹配引入的性能开销:

  • 使用 IIS 用户模式缓存并将 outboundRules> 元素的 <rewriteBeforeCache 属性设置为 true:

    <outboundRules rewriteBeforeCache="true">
    

    请注意,如果分块传输编码用于响应,则不应使用此设置。

  • 使用规则的 match 元素的匹配项属性。 例如,使用规则将某些 HTML 片段 <插入头> 元素,并且该规则具有搜索结束标记 - </head> 的模式时,可以设置 occurrences=“1”。 这会告知重写模块在找到 /head> 标记后<停止搜索其余响应。

    <match pattern="&lt;/head&gt;" occurrences="1" />
    

规则模式语法

可以使用规则的 patternSyntax 属性来指定规则模式语法。 此属性可设置为以下选项之一:

ECMAScript – Perl 兼容(ECMAScript 标准兼容)正则表达式语法。 这是任何规则的默认选项。 这是模式格式的示例:“^([_0-9a-zA-Z-]+/)?(wp-.*)”

Wild卡IIS HTTP 重定向模块中使用的 Wild卡 语法。 这是采用以下格式的模式示例:“/Scripts/*.js”,其中星号(“*”)表示“匹配任意数量的任意字符并在后引用中捕获它们”。 请注意,当规则没有任何标记筛选器时,不能使用 wild卡 模式类型。

ExactMatch - 在输入字符串内执行确切的字符串搜索。

patternSyntax 属性的范围是每个规则,这意味着它适用于当前规则的模式以及在该规则的条件中使用的所有模式。

规则模式属性

可以通过使用匹配>元素的<否定属性来否定模式。 使用此属性时,仅当输入字符串与指定的模式不匹配时,才会执行规则操作。

默认情况下,使用不区分大小写的模式匹配。 若要启用区分大小写,可以使用规则的 match> 元素的 <ignoreCase 属性。

规则条件

规则条件允许定义规则评估的其他逻辑,这些逻辑可以基于当前输入字符串以外的输入。 任何规则都可以有零个或多个条件。 规则条件在规则模式匹配成功后进行评估。

条件是在重写规则的条件>集合中<定义的。 此集合具有一个名为 logicalGrouping 的属性,用于控制条件的计算方式。 如果规则有条件,则仅当匹配规则模式并且:

  • 所有条件的计算结果均为 true,前提是使用了 logicalGrouping=“MatchAll”。
  • 如果 使用了 logicalGrouping=“MatchAny” ,则至少有一个条件的计算结果为 true。

通过指定以下属性来定义条件:

  • 输入字符串 - 条件输入指定要用作条件评估输入的项。 条件输入是一个任意字符串,可以包括服务器变量和对以前的条件模式和/或规则模式的回引用。

  • 模式 – 在条件输入中查找的模式。 可以使用正则表达式语法或使用 wild卡 语法来指定模式。 要在条件中使用的模式类型取决于为此条件所属的规则定义的 patternSyntax 标志的值。 此条件类型具有两个控制模式匹配的相关属性:

    • pattern – 使用此属性指定实际模式。
    • ignoreCase – 使用此属性控制条件的模式匹配是否应区分大小写或区分大小写。

规则操作

当输入字符串与规则模式匹配且条件评估成功(具体取决于规则配置、匹配的所有条件或匹配的任何一个或多个条件)时,将执行重写规则操作。 有两种类型的操作可用,操作配置元素的<>“type”属性可用于指定规则必须执行的操作。 以下部分介绍与特定操作类型相关的不同操作类型和配置选项。

重写操作

重写操作将当前规则输入字符串替换为替换字符串。 替换字符串在规则的操作>元素的值属性<内指定。 替换字符串是一个可以包括以下内容的自由格式字符串:

  • 对条件和规则模式的后退引用。 (有关详细信息,请参阅有关如何使用后引用的部分。
  • 服务器变量。 (有关详细信息,请参阅有关如何使用服务器变量的部分。

无操作

无操作用于指定不应执行任何操作。

从重写规则访问响应标头

可以使用与访问服务器变量相同的语法,但具有特殊的命名约定,从重写规则中获取任何响应 HTTP 标头的内容。 如果服务器变量以“RESPON标准版_”开头,则它将存储 HTTP 响应标头的内容,该标头的名称是使用以下命名约定确定的:

  1. 名称中的所有下划线(“_”)符号都转换为短划线符号(“-”)。
  2. 删除了“RESPON标准版_”前缀

例如,以下先决条件用于评估内容类型标头的内容

<preCondition name="IsHTML">
    <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>

设置请求标头和服务器变量

URL 重写模块 2.0 中的入站重写规则可用于设置请求标头和服务器变量。

允许的服务器变量列表

全局重写规则可用于设置任何请求标头和服务器变量,以及覆盖任何现有规则。 分布式重写规则只能设置/覆盖在允许的服务器变量允许的服务器变量允许的服务器>变量列表中定义的请求标头和服务器变量<。 如果分布式重写规则尝试设置允许的ServerVariables> 集合中<未列出的任何服务器变量或 HTTP 标头,则 URL 重写模块将生成运行时错误。 <默认情况下,allowedServerVariables> 集合存储在 applicationHost.config 文件中,只能由 IIS 服务器管理员修改。

使用入站重写规则设置请求标头和服务器变量

规则元素 <serverVariables> 用于定义要设置的服务器变量和 http 标头的集合。 仅当规则模式匹配且条件评估成功(具体取决于规则配置、匹配的所有条件或匹配的一个或多个条件)时,才会设置这些条件。 serverVariables> 集合中的每个<项都包含以下项:

  • 名称 - 指定要设置的服务器变量的名称。

  • - 指定服务器变量的值。 值是一个可以包括:

    • 对条件和规则模式的后退引用。 (有关详细信息,请参阅有关如何使用后引用的部分。
    • 服务器变量。 (有关详细信息,请参阅有关如何使用服务器变量的部分。
  • 替换 标志 - 指定是否覆盖服务器变量的值(如果已存在)。 默认情况下,将启用替换功能。

以下示例规则重写请求的 URL,并设置名称X_REQUESTED_URL_PATH的服务器变量:

<rule name="Rewrite to index.php" stopProcessing="true">
    <match url="(.*)\.htm$" />
    <serverVariables>
        <set name="X_REQUESTED_URL_PATH" value="{R:1}" />
    </serverVariables>
    <action type="Rewrite" url="index.php?path={R:1}" />
</rule>

注意:对于上述示例,需要向 allowedServerVariables> 集合添加X_REQUESTED_URL_PATH<:

<rewrite>
    <allowedServerVariables>
        <add name="X_REQUESTED_URL_PATH" />
    </allowedServerVariables>
</rewrite>

关于请求标头的说明

请求标头使用与服务器变量相同的机制来设置,但具有特殊的命名约定。 如果 serverVariables> 集合中的<服务器变量名称以“HTTP_”开头,则会导致根据以下命名约定设置 HTTP 请求标头:

  1. 名称中的所有下划线(“_”)符号都转换为短划线符号(“-”)。
  2. 所有字母都转换为小写。
  3. 已删除“HTTP_”前缀

例如,以下配置用于在请求上设置自定义 x-original-host 标头:

<set name="HTTP_X_ORIGINAL_HOST" value="{HTTP_HOST}" />

设置响应标头

URL 重写模块 2.0 中的出站重写规则可用于设置新的或修改现有响应 HTTP 标头。 响应 HTTP 标头使用与服务器变量相同的语法,并使用从重写规则访问响应标头中所述的命名约定,在出站规则中访问响应标头。

如果出站重写规则的 match> 元素的 <serverVariable 属性具有值,则它指示此重写规则将对相应响应标头的内容进行操作。 例如,以下规则设置响应标头“x-custom-header”:

<outboundRules>
    <rule name="Set Custom Header">
        <match serverVariable="RESPONSE_X_Custom_Header" pattern="^$" />
        <action type="Rewrite" value="Something" />
    </rule>
</outboundRules>

重写规则的模式将应用于指定响应标头的内容,如果规则的模式和可选条件成功评估,则将重写该响应标头的值。

在定义用于重写响应 HTTP 标头的逻辑时,正则表达式模式和轻松访问重写规则中的现有请求和响应标头提供了很多灵活性。 例如,以下重写规则可用于修改重定向响应中 Location 标头的内容:

<outboundRules>
    <!-- This rule changes the domain in the HTTP location header for redirection responses -->
    <rule name="Change Location Header">
        <match serverVariable="RESPONSE_LOCATION" pattern="^http://[^/]+/(.*)" />
        <conditions>
            <add input="{RESPONSE_STATUS}" pattern="^301" />
        </conditions>
        <action type="Rewrite" value="http://{HTTP_HOST}/{R:1}"/>
    </rule>
</outboundRules>

在重写规则中使用后退引用

可以在后引用中捕获规则或条件输入的一部分。 然后,这些 URL 可用于在规则操作中构造替换 URL,或为规则条件构造输入字符串。

返回引用以不同的方式生成,具体取决于规则使用哪种类型的模式语法。 使用 ECMAScript 模式语法时,可以通过将括号放在必须捕获后引用的模式的一部分周围来创建反向引用。 例如,模式 ([0-9]+)/([a-z]+).html 将从以下字符串中捕获 07文章07/article.html。 使用“Wild卡”模式语法时,始终在模式中使用星号符号 ~ 时创建后引用。

无论使用哪种模式语法来捕获它们,反向引用的用法都是相同的。 可以在重写规则中的以下位置使用后退引用:

  • 条件输入字符串

  • 在规则操作中,具体来说:

    • 入站规则中重写和重定向操作的 url 属性
    • 出站规则中重写操作的值属性
    • CustomResponse 操作的 statusLine 和 responseLine
  • 重写映射的关键参数

返回条件模式的引用由 {C:N} 标识,其中 N 从 0 到 9;对规则模式的后退引用由 {R:N} 标识,其中 N 从 0 到 9。 请注意,对于这两种类型的背引用,{R:0} 和 {C:0} 都将包含匹配的字符串。

例如,在此模式中:

^(www\.)(.*)$

对于字符串: www.foo.com 后退引用将按如下方式编制索引:

{C:0} - www.foo.com
{C:1} - www.
{C:2} - foo.com

跟踪跨条件的捕获组

默认情况下,在规则操作中,可以使用对规则模式的后退引用以及该规则的最后一个匹配条件。 例如,在此规则中:

<rule name="Back-references with trackAllCaptures set to false">
 <match url="^article\.aspx" >
 <conditions>
    <add input="{QUERY_STRING}" pattern="p1=([0-9]+)" />
    <add input="{QUERY_STRING}" pattern="p2=([a-z]+)" />  
 </conditions>
 <action type="Rewrite" url="article.aspx/{C:1}" /> <!-- rewrite action uses back-references to the last matched condition -->
</rule>

后引用 {C:1} 将始终包含第二个条件中的捕获组的值,即查询字符串参数 p2 的值。 p1 的值将不能作为后引用提供。

在 URL 重写模块 2.0 中,可以更改捕获组的索引方式。 启用对条件>集合的 <trackAllCaptures 设置会使捕获组形成所有匹配的条件,以便通过后引用提供。 例如,在此规则中:

<rule name="Back-references with trackAllCaptures set to true">
 <match url="^article\.aspx" >
 <conditions trackAllCaptures="true">
    <add input="{QUERY_STRING}" pattern="p1=([0-9]+)" />
    <add input="{QUERY_STRING}" pattern="p2=([a-z]+)" />  
 </conditions>
 <action type="Rewrite" url="article.aspx/{C:1}/{C:2}" /> <!-- rewrite action uses back-references to both conditions -->
</rule>

后引用 {C:1} 将包含第一个条件中的捕获组的值,而后引用 {C:2} 将包含第二个条件中的捕获组的值。

当 trackAllCaptures 设置为 true 时,条件捕获回引用由 {C:N} 标识,其中 N 从 0 到所有规则条件中的捕获组总数。 {C:0} 包含第一个匹配条件中的整个匹配字符串。 例如,对于以下两个条件:

<conditions trackAllCaptures="true">
    <add input="{REQUEST_URI}" pattern="^/([a-zA-Z]+)/([0-9]+)/$" />
    <add input="{QUERY_STRING}" pattern="p2=([a-z]+)" />  
 </conditions>

如果 {REQUEST_URI} 包含“/article/23/”,并且 {QUERY_STRING} 包含“p1=123&p2=abc”,则条件后引用将按如下所示编制索引:

{C:0} - “/article/23/”
{C:1} - “article”
{C:2} - “23”
{C:3} - “abc”

将重写 URL 记录到 IIS 日志中

可以将分布式入站重写规则配置为将重写 URL 记录到 IIS 日志文件中,而不是记录 HTTP 客户端请求的原始 URL。 若要启用重写 URL 的日志记录,请使用规则的操作>元素的 <logRewrittenUrl 属性,例如:

<rule name="set server variables">
    <match url="^article/(\d+)$" />
    <action type="Rewrite" url="article.aspx?id={R:1}" logRewrittenUrl="true" />
</rule>