使用 HttpModule 执行 URL 重写的时机选择
在 ASP.NET 级别执行 URL 重写时,可以使用 HTTP 模块或 HTTP 处理程序来执行重写。使用 HTTP 模块时,必须决定在请求有效期内的哪个时间点上来检查 URL 是否需要重写。乍一看,这似乎可以任意选择,但决定会以一种明显而微妙的方式对应用程序产生影响。由于内置 ASP.NET HTTP 模块使用 Request 对象的属性执行任务,因此选择在何处执行重写非常重要。(如上所述,重写路径将改变 Request 对象的属性值。)下面列出了这些密切相关的内置 HTTP 模块及其捆绑到的事件:
HTTP 模块 | 事件 | 说明 |
FormsAuthenticationModule | AuthenticateRequest | 确定用户是否通过了窗体身份验证。如果没有,用户将被自动重定向到指定的登录页面。 |
FileAuthorizationMoudle | AuthorizeRequest | 使用 Windows 身份验证时,此 HTTP 模块将检查以确保 Microsoft® Windows® 帐户对被请求的资源具有足够的权限。 |
UrlAuthorizationModule | AuthorizeRequest | 检查以确保请求者可以访问指定的 URL。通过 Web.config 文件中的 和 元素来指定 URL 授权。 |
如上所述,BeginRequest 事件在 AuthenticateRequest 之前触发,后者在 AuthorizeRequest(?) 之前触发。
可以执行 URL 重写的一个安全位置是在 BeginRequest 事件中。也就是说,如果 URL 需要重写,该操作将在任何一个内置 HTTP 模块运行前(?)执行。使用窗体身份验证时,这种方法存在一定的缺陷。如果您以前使用过窗体身份验证,您会了解当用户访问受限资源时,他们将被自动重定向到指定的登录页面。成功登录后,用户将被返回到他们第一次尝试访问的页面。
如果在 BeginRequest 或 AuthenticateRequest 事件中执行 URL 重写,登录页面(提交后)将把用户重定向到重写后的页面上。也就是说,假设用户在其浏览窗口中键入了 /people/ScottMitchell.aspx,此地址将被重写为 /info/employee.aspx?empID=1001。如果将 Web 应用程序配置为使用窗体身份验证,当用户第一次访问 /people/ScottMitchell.aspx 时,首先,URL 将被重写为 /info/employee.aspx?empID=1001;接下来,FormsAuthenticationModule 将运行,并将用户重定向到登录页面(如果需要)。但是,用户在成功登录后将被发送到 /info/employee.aspx?empID=1001,因为当 FormsAuthenticationModule 运行后,此 URL 即是请求的 URL。
同样,在 BeginRequest 或 AuthenticateRequest 事件中执行重写时,UrlAuthorizationModule 看到的将是重写后的 URL。也就是说,如果您在 Web.config 文件中使用 元素来为特定的 URL 指定授权,则必须引用重写后的 URL。
要解决这些细微问题,您可以决定在 AuthorizeRequest 事件中执行 URL 重写。此方法解决了 URL 授权和窗体身份验证的一些问题,但同时也产生了新的问题:文件授权无法工作。使用 Windows 身份验证时,FileAuthorizationModule 将检查以确保通过身份验证的用户具有访问特定 ASP.NET 页面的相应权限。
假设一组用户对 C:/Inetput/wwwroot/info/employee.aspx 没有 Windows 级别的文件访问权限,并要尝试访问 /info/employee.aspx?empID=1001,他们将会收到授权错误消息。但是,如果我们将 URL 重写移到 AuthenticateRequest 事件中,当 FileAuthorizationModule 检查安全设置时,仍然认为被请求的文件是 people/ScottMitchell.aspx,因为该 URL 必须被重写。因此,文件授权检查将通过,允许此用户查看重写后的 URL /info/employee.aspx?empID=1001 的内容。
那么,应该何时在 HTTP 模块中执行 URL 重写?
这取决于要使用的身份验证类型。如果不想使用任何身份验证,则无论 URL 重写发生在 BeginRequest、AuthenticateRequest 还是 AuthorizeRequest 中都没有什么关系。如果要使用窗体身份验证而不使用 Windows 身份验证,请将 URL 重写放在 AuthorizeRequest 事件处理程序中执行。最后,如果要使用 Windows 身份验证,请在 BeginRequest 或 AuthenticateRequest 事件进行过程中安排 URL 重写。
http://www.microsoft.com/china/msdn/library/webservices/asp.net/URLRewriting.mspx?mfr=true
不知道这是谁翻译的,看了两遍,就是觉得文中有些地方有明显的错误,即上文中红色部分。
豁然一想这是否有原版英文的呢,在msdn搜索"URLRewriting",果然有篇英文的:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/urlrewriting.asp
对比了一下,确实中文翻译有误,:( ~
HTTP 模块和 global.asax 的取舍
先看各自的特点:
1) 二者都包含处理 HttpApplication 事件的事件处理方法
2) global.asax 能收到会话和应用的开始和结束事件通知;HTTP 模块不能处理这些事件
3) 模块部署在机器(machine.config)或者虚拟目录(web.config)级;global.asax 只能用在目录级上
所以如果针对的是服务器上的所有应用,或者作为一个组建产品,则最好选用 HTTP 模块;如果是用于特定的应用,则选择 global.asax 文件。