将自定义重写提供程序与 URL 重写模块配合使用

作者:Ruslan Yakushev

本演练指导你将自定义重写提供程序与 URL 重写模块 2.0 配合使用。 本演练使用 URL 重写 2.0 扩展性示例,可以从 MSDN 代码库的“URL 重写扩展性示例”下载这些示例。

安装 URL 重写扩展性示例

若要完成本演练,需要下载并安装 URL 重写扩展性示例 (https://www.microsoft.com/download/details.aspx?id=43353)。 扩展性示例安装包包含 .NET 程序集和源代码,以及用于三种最常见用例的重写提供程序的完整实现:

  • 将重写或重定向映射存储在 SQL 数据库中;
  • 将重写或重定向映射存储在文本文件中;
  • 将查找子字符串存储在文本文件中。

在安装过程中,请确保在自定义安装中选择“运行时”选项。 这会在 .NET 全局程序集缓存中注册示例提供程序,以便 URL 重写模块可以使用它们。

“I I S U R L 重写扩展性示例设置”对话框的屏幕截图。突出显示“运行时”图标。

注册提供程序

安装包中包含 3 个重写提供程序:

  • DbProvider - 此提供程序可用于通过执行存储过程从 SQL Server 数据库表检索重写映射
  • FileMapProvider - 此提供程序可用于检索存储在文本文件中的重写映射
  • FileContainsProvider - 此提供程序可用于检查文本文件中的任何字符串是否为提供程序输入字符串的子字符串。

若要在重写规则中使用示例提供程序,必须在 IIS 中注册提供程序。 若要注册提供程序,可以使用 IIS 管理器用户界面:

  1. 在 IIS 管理器中打开“URL 重写”功能;
  2. 在右侧的“操作”窗格中选择“查看提供程序...”操作;
    I S Manager U R L 重写主页的屏幕截图。在右侧的“操作”窗格中,突出显示了“视图提供程序”。
  3. 在“操作”窗格中选择“添加提供程序...”操作;
  4. 在“添加提供程序”对话框中,输入从重写规则引用该提供程序时要使用的名称。
  5. 然后,在“托管类型”下拉列表中为提供程序选择相应的 .NET 类型。 请注意,提供程序类型可能需要在一段时间后才显示在此处。
    “I S 管理器”页的屏幕截图。将显示“重写提供程序”页。在右侧的“操作”窗格中,突出显示了“添加提供程序”。
  6. 重复上述步骤来注册所有三个提供程序。

使用 DbProvider

若要使用 DbProvider,需要有权访问 Microsoft SQL Server。 该提供程序连接到 SQL Server 数据库并执行一个存储过程,该存储过程采用包含输入 URL 字符串的 NVARCHAR 输入参数,并返回包含 NVARCHAR 类型的输出 URL 字符串的一行一列结果集。

创建示例数据库

打开 SQL Server Management Studio,然后打开新的查询窗口并执行以下 SQL 脚本:

USE [master]

CREATE LOGIN [IIS APPPOOL\DefaultAppPool] FROM WINDOWS WITH DEFAULT_DATABASE=[master]

CREATE DATABASE [RewriteDB]
GO

USE [RewriteDB]
GO

CREATE TABLE [dbo].[RewriteTable](
[OriginalUrl] [nvarchar](256) NOT NULL,
[NewUrl] [nvarchar](256) NOT NULL
) ON [PRIMARY]
GO

CREATE PROCEDURE [dbo].[GetRewrittenUrl] 
@input nvarchar(256)
AS
SELECT rt.NewUrl 
FROM dbo.RewriteTable rt 
WHERE rt.OriginalUrl = @input
GO

CREATE USER [IIS APPPOOL\DefaultAppPool] FOR LOGIN [IIS APPPOOL\DefaultAppPool]

GRANT EXECUTE ON dbo.GetRewrittenUrl TO [IIS APPPOOL\DefaultAppPool];
GO

INSERT INTO dbo.RewriteTable VALUES ('old/catalog/product.html', 'new/category/product.html');
INSERT INTO dbo.RewriteTable VALUES ('old/contactus/index.html', 'new/contactus.html');
GO

上述脚本创建一个名为 RewriteDB 的新数据库,其中包含一个表 RewriteTable 和一个存储过程 GetRewrittenURL。 它还向 IIS APPPOOL\DefaultAppPool 帐户授予执行该存储过程的权限。 它还使用两个 URL 映射来填充数据库表。

配置 DbProvider 设置

配置 DbProvider 实例以调用存储过程:

  1. 在 IIS 管理器的“URL 重写”功能视图中,在“操作”窗格中选择“查看提供程序...”。
  2. 选择“添加提供程序”,然后选择“DbProvider”。 将其命名为 DB;这是用于在重写规则中引用提供程序的名称
  3. 选择名为 DB 的 DbProvider 实例,然后单击“添加提供程序设置...”操作。
  4. 使用“编辑提供程序设置”对话框配置提供程序:
    “I S 管理器”页的屏幕截图。将显示“重写提供程序”页。此时会显示“编辑提供程序设置”对话框,并在“名称”框中显示文本 S Q L Server 连接字符串。

为提供程序设置使用以下值:

  • SQL Server 连接字符串:提供 SQL Server 连接字符串,例如
    “Data Source=servername\sqlexpress;Initial Catalog=RewriteDB;Integrated Security=True”
  • 存储过程名称:GetRewrittenUrl
  • 缓存间隔(分钟):如果 SQL 表中的值未更改,则设置为 0,或者设置为正整数,以便提供程序定期刷新模块的内部重写缓存。 如果未指定,则假设值为 0。

从重写规则调用 DbProvider

打开网站根目录中的 web.config 文件。 如果使用 IIS 默认网站,则该文件应位于 C:\inetpub\wwwroot\ 文件夹中。

将以下重定向规则粘贴到 web.config 文件的 /<configuration>/<system.webServer>/<rewrite>/<rules> 元素内:

<rule name="DbProviderTest" stopProcessing="true">
    <match url="(.*)" />
    <conditions>
        <add input="{DB:{R:1}}" pattern="(.+)" />
    </conditions>
    <action type="Redirect" url="{C:1}" />
</rule>

web.config 文件的完整内容应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
    <providers>
        <provider name="DB" type="DbProvider, Microsoft.Web.Iis.Rewrite.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <settings>
                <add key="ConnectionString" value="Data Source=ruslany-server\sqlexpress;Initial Catalog=RewriteDB;Integrated Security=True" />
                <add key="StoredProcedure" value="GetRewrittenUrl" />
                <add key="CacheMinutesInterval" value="0" />
            </settings>
        </provider>
    </providers>
    <rules>
        <rule name="DbProviderTest" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
                <add input="{DB:{R:1}}" pattern="(.+)" />
            </conditions>
            <action type="Redirect" url="{C:1}" />
        </rule>
    </rules>
</rewrite>

此规则执行 HTTP 重定向到通过 DbProvider 从 SQL Server 数据库获取的 URL 的操作。 名为“DB”的 DbProvider 实例从规则的条件中调用,如果从提供程序返回的结果不为空,则执行 HTTP 重定向。

若要测试规则,请打开 Web 浏览器并向 http://localhost/old/catalog/product.htmlhttp://localhost/old/contactus/index.html 发出请求。 请注意,浏览器会根据 RewriteDB 数据库表中定义的重定向映射重定向到新 URL。 Web 服务器将返回重定向 URL 的 HTTP 404 错误,因为服务器上没有此类文件或目录,但这与本演练的目的无关。 重要的是,Web 服务器根据使用 DbProvider 的规则发出了重定向响应。

使用 FileMapProvider

FileMapProvider 从文本文件中读取 URL 映射。 当重写映射条目的数量非常大并且将其保存在 web.config 文件中不切实际时,可以使用它来代替内置重写映射功能。

创建示例映射文件

在网站的根目录中创建一个名为 App_Data 的新目录。 在该目录中创建一个名为 redirectmappings.txt 的文本文件。 将以下行添加到该文件中:

old/catalog/product.html, new/category/product.html
old/contactus/index.html, new/contactus.html

显示警告注释之前显示警告符号的图像。警告:始终确保无法直接从 Web 访问文本文件。 使用 IIS 请求筛选模块或将文件放置在 App_Data 文件夹中,以防止 HTTP 客户端直接访问该文件的内容。

配置 FileMapProvider

按照配置 DbProvider 中所述的相同步骤配置 FileMapProvider。 为提供程序设置使用以下值:

  • FilePath:{DOCUMENT_ROOT}\App_Data\redirectmappings.txt(请注意文件路径中 {DOCUMENT_ROOT} 的用法。在提供程序初始化期间,该路径将替换为实际路径。当你不想在 web.config 文件中放置绝对文件路径时,这很有用)
  • IgnoreCase:1
  • Separator:“,”(如果未指定,则使用制表符作为分隔符)

从重写规则调用 FileMapProvider

打开网站根目录中的 web.config 文件。 如果使用 IIS 默认网站,则该文件应位于 C:\inetpub\wwwroot\ 文件夹中。

将以下重定向规则粘贴到 web.config 文件的 /<configuration>/<system.webServer>/<rewrite>/<rules> 元素内:

<rule name="FileMapProviderTest" stopProcessing="true">
    <match url="(.*)" />
    <conditions>
        <add input="{FileMap:{R:1}}" pattern="(.+)" />
    </conditions>
    <action type="Redirect" url="{C:1}" />
</rule>

web.config 文件的完整内容应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
    <providers>
        <provider name="FileMap" type="FileMapProvider, Microsoft.Web.Iis.Rewrite.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <settings>
                <add key="FilePath" value="{DOCUMENT_ROOT}\App_Data\redirectmappings.txt" />
                <add key="IgnoreCase" value="1" />
                <add key="Separator" value="," />
            </settings>
        </provider>
    </providers>
    <rules>
        <rule name="FileMapProviderTest" stopProcessing="true">
            <match url="(.*)" />
            <conditions>
                <add input="{FileMap:{R:1}}" pattern="(.+)" />
            </conditions>
            <action type="Redirect" url="{C:1}" />
        </rule>
    </rules>
</rewrite>

此规则执行 HTTP 重定向到通过 FileMapProvider 从文本文件获取的 URL 的操作。 名为“FileMap”的 FileMapProvider 实例从规则的条件中调用,如果从提供程序返回的结果不为空,则执行 HTTP 重定向。

若要测试规则,请打开 Web 浏览器并向 http://localhost/old/catalog/product.htmlhttp://localhost/old/contactus/index.html 发出请求。 请注意,浏览器会根据 redirectmappings.txt 文件中定义的重定向映射重定向到新 URL。 Web 服务器将返回重定向 URL 的 HTTP 404 错误,因为服务器上没有此类文件或目录,但这与本演练的目的无关。 重要的是,Web 服务器根据使用 FileMapProviders 的规则发出了重定向响应。

使用 FileContainsProvider

FileContainsProvider 从文本文件中读取字符串集,然后检查提供程序的输入字符串是否包含其中的任何字符串作为子字符串。 例如,提供程序可与基于用户代理标头阻止访问的重写规则一起使用。

创建一个禁止用户代理文件的示例

在网站的根目录中创建一个名为 App_Data 的新目录。 在该目录中创建一个名为 disalloweduseragents.txt 的文本文件。 将以下行添加到该文件中:

badrobot1
badrobot2

警告符号的图像显示在警告注释之前。图像是中间带有感叹号的三角形。警告:始终确保无法直接从 Web 访问文本文件。 使用 IIS 请求筛选模块或将文件放置在 App_Data 文件夹中,以防止 HTTP 客户端直接访问该文件的内容。

配置 FileContainsProvider

按照配置 DbProvider 中所述的相同步骤配置 FileMapProvider。 为提供程序设置使用以下值:

  • FilePath:{DOCUMENT_ROOT}\App_Data\disalloweduseragents.txt(请注意文件路径中 {DOCUMENT_ROOT} 的用法。在提供程序初始化期间,该路径将替换为实际路径。当你不想在 web.config 文件中放置绝对文件路径时,这很有用)
  • IgnoreCase:1

从重写规则调用 FileContainsProvider

打开网站根目录中的 web.config 文件。 如果使用 IIS 默认网站,则该文件应位于 C:\inetpub\wwwroot\ 文件夹中。

将以下重定向规则粘贴到 web.config 文件的 /<configuration>/<system.webServer>/<rewrite>/<rules> 元素内:

<rule name="FileContainsProviderTest" stopProcessing="true">
    <match url=".*" />
    <conditions>
        <add input="{FileContains:{HTTP_USER_AGENT}}" pattern=".+" />
    </conditions>
    <action type="AbortRequest" />
</rule>

web.config 文件的完整内容应如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<rewrite>
    <providers>
        <provider name="FileContains" type="FileContainsProvider, Microsoft.Web.Iis.Rewrite.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
            <settings>
                <add key="FilePath" value="{DOCUMENT_ROOT}\App_Data\disalloweduseragents.txt" />
                <add key="IgnoreCase" value="1" />
            </settings>
        </provider>
    </providers>
    <rules>
        <rule name="FileContainsProviderTest" stopProcessing="true">
            <match url=".*" />
            <conditions>
                <add input="{FileContains:{HTTP_USER_AGENT}}" pattern=".+" />
            </conditions>
            <action type="AbortRequest" />
        </rule>
    </rules>
</rewrite>

如果 HTTP 请求的用户代理与 disalloweduseragents.txt 文件中列出的任何字符串匹配,则此规则将中止 HTTP 连接。 名为“FileContains”的 FileContainsProvider 实例是从规则的条件中调用的,如果从提供程序返回的结果不为空,则 HTTP 连接将会中止。

若要测试规则,请打开 WFetch 并向请求添加用户代理标头,如下所示:

user-agent: badrobot1\r\n

从 WFetch 向 http://localhost/test/ 发出请求。 你应会看到连接已中止,因为用户代理字符串与 disalloweduseragents.txt 文件中的字符串之一匹配。

w 提取一个对话框页面的屏幕截图。连接已中止,因为用户代理字符串已匹配不允许的用户代理 t x t 文件中的某个字符串。