工作原理: http://www.microsoft.com/china/technet/security/guidance/secmod37.mspx
URL Rewriting in asp.net: http://msdn2.microsoft.com/en-us/library/ms972974.aspx
在Asp.net中执行URL重写: http://www.microsoft.com/china/msdn/library/webservices/asp.net/URLRewriting.mspx?mfr=true
技巧/诀窍:在asp.net中重写URL: http://blog.joycode.com/scottgu/archive/2007/03/01/94004.aspx
慎用URL重写: http://www.cnblogs.com/csky/archive/2006/08/09/urlrewrite.html
Asp.net管道处理和HttpApplication中的事件处理顺序(From《工作原理》):
HttpApplication 类的实例是在 ASP.NET 基础结构中创建的,而不是由用户直接创建的。HttpApplication 类的一个实例在其生存期内被用于处理多个请求,但它一次只能处理一个请求。这样,成员变量才可用于存储针对每个请求的数据。
应用程序按照以下顺序执行由 global.asax 文件中定义的模块或用户代码处理的事件:
- BeginRequest
- AuthenticateRequest
- PostAuthenticateRequest
- AuthorizeRequest
- PostAuthorizeRequest
- ResolveRequestCache
- PostResolveRequestCache
在 PostResolveRequestCache 事件之后、PostMapRequestHandler 事件之前创建一个事件处理程序(对应于请求 URL 的页)。 - PostMapRequestHandler
- AcquireRequestState
- PostAcquireRequestState
- PreRequestHandlerExecute
执行事件处理程序。 - PostRequestHandlerExecute
- ReleaseRequestState
- PostReleaseRequestState
在 PostReleaseRequestState 事件之后,响应筛选器(如果有)将对输出进行筛选。 - UpdateRequestCache
- PostUpdateRequestCache
- EndRequest
我们应该在哪个事件中重写URL(From《在Asp.net中执行URL重写》):
可以执行 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 文件中使用
要解决这些细微问题,您可以决定在 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 必须被重写(感觉这句话有问题,这句话的英文原文:However, if we move the URL rewriting to the AuthenticateRequest event, when the FileAuthorizationModule checks the security settings, it still thinks the file being requested is /people/ScottMitchell.aspx, since the URL has yet to be rewritten。其中的"has yet to be rewriten"语义是指将要被重写但还没有被重写,显然这里就有逻辑错误了,参照上面的HttpApplication事件的触发顺序,我们将 URL 重写移到 AuthenticateRequest 事件中,那么先执行验证请求AuthenticateRequest事件时,就已经把用户请求的url重写成/info/employee.aspx?empID=1001了,所以再下一步授权请求FileAuthorizationModule中,asp.net是对重写后的url:/info/employee.aspx进行文件授权,所以当用户没有Windows级别的文件访问权限时,是不能被检查通过的,也就不存在其中描述的能查看该页面的情况。所以我觉得这句话的英文版本中叙述有误,中文版就错得更离谱了....)。因此,文件授权检查将通过,允许此用户查看重写后的 URL /info/employee.aspx?empID=1001 的内容。
那么,应该何时在 HTTP 模块中执行 URL 重写?这取决于要使用的身份验证类型。
如果不想使用任何身份验证,则无论 URL 重写发生在 BeginRequest、AuthenticateRequest 还是 AuthorizeRequest 中都没有什么关系。
如果要使用窗体身份验证而不使用 Windows 身份验证,请将 URL 重写放在 AuthorizeRequest 事件处理程序中执行。
最后,如果要使用 Windows 身份验证,请在 BeginRequest 或 AuthenticateRequest 事件进行过程中安排 URL 重写.