使用 URL 重写 v2 和应用程序请求路由的反向代理
本演练指导你使用 URL 重写模块和应用程序请求路由 (ARR) 来为多个后端应用程序实现反向代理服务器。
先决条件
若要运行本演练,必须满足以下要求:
- 启用了 ASP.NET 角色服务的 IIS 7 或更高版本。
- 已安装 URL 重写模块(如果你要完成有关响应重写的部分,则需要安装版本 2.0)
- 已安装应用程序请求路由版本 1.0 或版本 2.0
介绍
使用 URL 重写模块和应用程序请求路由,可以实现复杂且灵活的负载均衡和反向代理配置。 一种很常见的反向代理方案是通过 Internet 提供多个内部 Web 应用程序。 可通过 Internet 访问的 Web 服务器用作反向代理服务器,它接收 Web 请求,然后将其转发给多个 Intranet 应用程序进行处理:下图演示了反向代理方案的典型配置:
假设 ARR 服务器具有域名 http://contoso.com
,可以使用以下 URL 访问每个 Web 应用程序:
http://contoso.com/webmail/
http://contoso.com/payroll/
向 http://contoso.com/webmail/default.aspx
发出请求时,ARR 会使用 URL http://webmail/default.aspx
将这些请求转发到内部服务器。 同样,对 http://contoso.com/payroll/
的请求将转发到 http://payroll/default.aspx
。
此外,如果内部应用程序在其响应 HTML 中插入链接到这些应用程序中其他位置的链接,则应在响应返回到客户端之前修改这些链接。 例如,http://webmail/default.aspx
中的页面可能包含如下链接:
<a href="/default.aspx?id=1">link</a>
然后 ARR 服务器应将此链接更改为以下内容:
<a href="/webmail/default.aspx?id=1">link</a>
创建示例网站
为简单起见,将在单个服务器上实现要在本演练中使用的反向代理方案,IIS 的“默认网站”充当反向代理站点及 webmail 和 payroll 应用程序(托管在同一服务器上的单独 IIS 网站中)。
若要创建示例网站,请执行以下操作:
在以下文件夹中创建名为“webmail”和“payroll”的两个文件夹:
%SystemDrive%\inetpub\ folder.
创建名为“webmail”和“payroll”的两个 IIS 网站,它们指向
%SystemDrive%\inetpub\
下的相应文件夹。 为每个站点使用不同的 IP 端口。
可使用以下命令来创建站点:%windir%\System32\inetsrv\appcmd.exe add site /name:"webmail" /bindings:http/*:8081: /physicalPath:"%SystemDrive%\inetpub\webmail" %windir%\System32\inetsrv\appcmd.exe add site /name:"payroll" /bindings:http/*:8082: /physicalPath:"%SystemDrive%\inetpub\payroll"
在以下文件夹中创建一个名为 default.aspx 的文件:
%SystemDrive%\inetpub\webmail
复制以下 ASP.NET 标记,将其粘贴到文件中,并保存该文件:
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Reverse Proxy Test - WebMail Application</title> </head> <body> <h1>Reverse Proxy Test Page - WebMail Application</h1> <p>Requested URL path is <%= Request.ServerVariables["SCRIPT_NAME"] %><p> <p><a href="<%= Request.ServerVariables["SCRIPT_NAME"] %>">Here</a> is the link to this page.</p> </body> </html>
在以下文件夹中创建一个名为 default.aspx 的文件:
%SystemDrive%\inetpub\payroll
复制以下 ASP.NET 标记,将其粘贴到文件中,并保存该文件:
<%@ Page Language="C#" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Reverse Proxy Test - Payroll Application</title> </head> <body> <h1>Reverse Proxy Test Page - Payroll Application</h1> <p>Requested URL path is <%= Request.ServerVariables["SCRIPT_NAME"] %><p> <p><a href="<%= Request.ServerVariables["SCRIPT_NAME"] %>">Here</a> is the link to this page.</p> </body> </html>
若要确保站点正常工作,请打开 Web 浏览并请求以下 URL:
http://localhost:8081/default.aspx
http://localhost:8082/default.aspx
为反向代理配置规则
在本演练部分,你将配置反向代理功能以使用创建的示例网站。
启用反向代理功能
默认情况下,反向代理功能处于禁用状态,因此必须首先启用它。
为 Webmail 应用程序创建规则
创建两个重写规则:
- 只要请求的 URL 路径以“webmail”开头,其中一个重写规则就会通过代理将任何请求中转到
http://localhost:8081/
处的 webmail 应用程序。 - 只要请求的 URL 路径以“payroll”开头,另一个重写规则就会通过代理将任何请求中转到
http://localhost:8082/
处的 payroll 应用程序。
若要添加反向代理重写规则,请执行以下操作:
打开位于以下位置的 web.config 文件:
%SystemDrive%\inetpub\wwwroot\
在 /configuration/system.webServer 元素下添加以下内容,然后保存文件:
<rewrite> <rules> <rule name="Reverse Proxy to webmail" stopProcessing="true"> <match url="^webmail/(.*)" /> <action type="Rewrite" url="http://localhost:8081/{R:1}" /> </rule> <rule name="Reverse Proxy to payroll" stopProcessing="true"> <match url="^payroll/(.*)" /> <action type="Rewrite" url="http://localhost:8082/{R:1}" /> </rule> </rules> </rewrite>
有关创建重写规则的详细信息,请参阅为 URL 重写模块创建重写规则。
测试反向代理功能
打开 Web 浏览器并向 http://localhost/webmail/default.aspx
发出请求。 应会看到来自 webmail 测试页的响应。 另外,请向 http://localhost/payroll/default.aspx
发出请求。 应会看到来自 payroll 测试页的响应。
请注意,在这两种情况下,响应内部的链接都指向 http://localhost/default.aspx
。 如果你单击此链接,服务器将返回 404(找不到文件)响应。 在下一部分,你将了解如何创建出站规则来修复应用程序生成的响应 HTML 的链接。
为响应重写配置规则
本文档部分适用于 IIS 7 的 URL 重写模块版本 2.0。
你将定义一个出站规则来替换响应 HTML 中的所有链接,如下所示:
<a href="/default.aspx">...</a>
将被替换为:
<a href="/webmail/default.aspx">...</a>
(如果响应来自 webmail 应用程序)
和
<a href="/payroll/default.aspx">...</a>
(如果响应来自 payroll 应用程序)
警告
当响应头或响应内容被出站重写规则修改时,应格外小心,以确保插入响应中的文本不包含任何客户端可执行代码,否则可能会导致跨站点脚本漏洞。 当重写规则使用不受信任的数据(例如 HTTP 标头或查询字符串)来生成要插入到 HTTP 响应中的字符串时,这一点尤其重要。 在这种情况下,替换字符串应使用 HtmlEncode 函数进行 HTML 编码,例如:
<action type="Rewrite" value="{HtmlEncode:{HTTP_REFERER}}" />
若要创建规则,请执行以下步骤:
- 转到 IIS 管理器
- 选择“默认网站”
- 在功能视图中,单击“URL 重写”
- 在右侧的操作窗格中,单击“添加规则...”。 在“添加规则”对话框中,选择“出站规则”类别下的“空白规则”,然后单击“确定”:
现在必须定义实际的出站规则。 在 URL 重写模块 2.0 中,出站重写规则是通过指定以下信息来定义的:
- 规则名称。
- 用于控制是否应将此规则应用于响应的可选前提条件。
- 用于匹配响应中的字符串的模式。
- 一组可选条件。
- 当模式匹配并且所有条件检查都成功时要执行的操作。
为规则命名
在“名称”文本框中输入用于唯一标识规则的名称,例如:“添加应用程序前缀”。
定义前提条件
前提条件用于评估是否应对响应执行出站规则评估。 例如,如果修改 HTML 内容的规则,则仅应根据此规则评估内容类型标头设置为“text/html”的 HTTP 响应。 出站规则评估和内容重写是 CPU 密集型操作,可能会对 Web 应用程序的性能产生负面影响。 因此,在应用出站规则时,请使用前提条件来缩小范围。
由于创建的规则应仅应用于 HTML 响应,因此需要定义一个前提条件来检查 HTTP 响应头 content-type 是否等于“text/html”。
若要定义前提条件,请执行以下操作:
在“前提条件”列表中,选择“<创建新的前提条件...>”。
随即你会转到“前提条件编辑器”对话框,需要在其中定义前提条件。 如下所述指定前提条件设置:
单击“确定”保存前提条件并返回到“编辑规则”页。
定义匹配范围
出站重写规则可以对 HTTP 标头的内容或响应正文内容进行操作。 该规则需要替换响应内容中的链接,因此请在“匹配范围”下拉列表中选择“响应”。
定义标记筛选器
标记筛选器用于将模式匹配范围限定为仅与特定 HTML 元素匹配,而不是根据规则的模式评估整个响应。 模式匹配是一项非常消耗 CPU 资源的操作,如果根据模式评估整个响应,可能会显著减慢 Web 应用程序的响应速度。 标记筛选器允许指定仅在某些 HTML 标记的内容中应用模式匹配,从而显著减少必须根据正则表达式模式进行评估的数据量。
若要定义标记筛选器,请展开下拉列表“匹配以下范围的内容:”,然后选中复选框“A (href 属性)”。
这会将规则设置为仅将模式应用于超链接的 href 属性值,如以下示例所示:
<a href="this string will be used for pattern matching">Some link</a>
定义模式
在“模式”文本框中输入以下字符串:
^/(.*)
此字符串是一个正则表达式,指定模式将匹配任何以“/”符号开头的 URL 路径字符串。
请注意模式中括号的用法。 这些括号创建一个捕获组,稍后可以使用反向引用在规则中引用该捕获组。
定义条件
仅当响应来自 webmail 或 payroll 应用程序时,才需要更改响应 HTML 中的链接。 检查是否要使用分析客户端所请求 URL 路径的条件。 另外定义一个条件模式,用于从请求的 URL 捕获应用程序文件夹,以便规则在重写响应中的链接时可以重用该模式。
- 展开条件组框。
- 单击“添加...”按钮,显示用于定义条件的对话框的。
- 对于“条件输入:”,请输入以下字符串:“{URL}”。 这会将 URL 重写模块配置为使用 Web 客户端请求的 URL 路径。
- 在下拉列表组合框中,选择“匹配模式”。
- 在“模式”文本框中输入
^/(webmail|payroll)/.*
。 此正则表达式用于匹配以/webmail
或/payroll
开头的 URL 路径。 模式中的括号捕获所匹配的 URL 字符串的一部分,以便可在构造替换 URL 时使用它。 - 单击“确定”保存条件并返回到“添加规则”UI。
定义操作
选择“操作”组框中列出的“重写”操作类型。 在“值”文本框中,输入以下字符串:
/{C:1}/{R:1}
此字符串指定链接地址应重写为的新值。 {C:1} 是对条件模式捕获组的反向引用,它将由“webmail”或“payroll”字符串替换。 {R:1} 是对规则模式捕获组的反向引用,在这种特定的情况下,它将替换为超链接中使用的原始 URL 路径。
保留所有其他设置的默认值。 “编辑出站规则”属性页应如下所示:
单击右侧的“应用”操作保存规则。
若要检查我们刚刚创建的规则的配置,请打开位于 %SystemDrive%\inetput\wwwroot\
中的 web.config 文件。 在此文件中,应会看到包含此规则定义的 <rewrite>
部分:
<rewrite>
<rules>
<rule name="Reverse Proxy to webmail" stopProcessing="true">
<match url="^webmail/(.*)" />
<action type="Rewrite" url="http://localhost:8081/{R:1}" />
</rule>
<rule name="Reverse Proxy to payroll" stopProcessing="true">
<match url="^payroll/(.*)" />
<action type="Rewrite" url="http://localhost:8082/{R:1}" />
</rule>
</rules>
<outboundRules>
<rule name="Add application prefix" preCondition="IsHTML">
<match filterByTags="A" pattern="^/(.*)" />
<conditions>
<add input="{URL}" pattern="^/(webmail|payroll)/.*" />
</conditions>
<action type="Rewrite" value="/{C:1}/{R:1}" />
</rule>
<preConditions>
<preCondition name="IsHTML">
<add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
</preCondition>
</preConditions>
</outboundRules>
</rewrite>
测试规则
若要测试规则是否在响应中正确重写 URL,请打开 Web 浏览器并向 http://localhost/webmail/default.aspx
或 http://localhost/payroll/default.aspx
发出请求。 应会看到出站重写规则已更改 HTML 响应中的链接:
总结
在本演练中,你已了解如何配置 URL 重写模块和应用程序请求路由来实现反向代理方案。 此外,你还了解了如何使用 URL 重写模块 2.0 的新出站重写功能来修复应用程序响应中的链接,然后将其提供给 Web 客户端。
请注意,使用反向代理时,通常还需要重写 HTTP 响应头。 若要了解如何使用 URL 重写模块 2.0 修改响应 HTTP 标头,请参阅修改 HTTP 响应头。