引言
Http 请求处理流程和Http Handler 介绍这两篇文章里,我们首先了解了Http请求在服务器端的处理流程,随后我们知道Http请求最终会由实现了IHttpHandler接口的类进行处理(应该记得Page类实现了IHttpHandler)。从Http 请求处理流程一文的最后的一幅图中可以看到,在Http请求由IHttpHandler处理之前,它需要通过一系列的Http Module;在请求处理之后,它需要再次通过一系列的Http Module,那么这些Http Module是如何组成的?用来做什么呢?本文将对Http Module作以介绍。
Http Module概述
暂时先不考虑我们自己实现Http Module的情况。在.Net中,Http Module 是实现了IHttpModule接口的程序集。IHttpModule 接口本身并没有什么好大写特写的,由它的名字可以看出,它不过是一个普普通通的接口而已。实际上,我们关心的是实现了这些接口的类,如果我们也编写代码实现了这个接口,那么有什么用途。一般来说,我们可以将Asp.Net中的事件分成三个级别,最顶层是 应用程序级事件、其次是页面级事件、最下面是控件级事件,事件的触发分别与 应用程序周期、页面周期、控件周期紧密相关。而 Http Module 的作用是与应用程序事件密切相关的。
我们通过Http Module在Http请求管道(Pipeline)中注册期望对应用程序事件做出反应的方法,在相应的事件触发的时候(比如说BeginRequest事件,它在应用程序收到一个Http请求并即将对其进行处理时触发),便会调用Http Module注册了的方法,实际的工作在这些方法中执行。.Net 本身已经有很多的Http Module,其中包括 表单验证Module(FormsAuthenticationModule), session 状态Module(SessionStateModule),输出缓存Module (OutputCacheModule)等。
注册 Http Module
在注册我们自己编写的 Http Module 之前,先来看看Asp.Net中已经有的HttpModule。与 Http Handler类似,我们需要打开机器上C:/WINDOWS/Microsoft.NET/Framework/ v2.0.50727/CONFIG 目录下的 web.config 文件。找到 <httpModules/> 结点,应该可以看到下面的内容:
<httpModules> <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" /> <add name="Session" type="System.Web.SessionState.SessionStateModule" /> <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" /> <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" /> <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" /> <add name="RoleManager" type="System.Web.Security.RoleManagerModule" /> <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />... 略</httpModules>
我们先从结点上看,type属性与上一节所说的http handler结点的type属性类似,都代表了相应的程序集。但是,与http handler 不同,module只提供了一个name属性,没有诸如 path这样指定某一特定(或者用通配符 * 代表某一种类)文件的处理程序。这是与Module的特点相关的,我们知道 module 是响应应用程序周期中触发的事件,对于所有提交到aspnet_isapi.dll的请求都一样,即便请求只是像类似http://www.tracefact.net/images/logo.gif 这样获取一张图片而已(对ISAPI进行过设置以后,默认aspnet_isapi.dll不接手图片文件)。
与Http handler类似,在这册我们自己的http module 时,假设类名为ModuleDemo,位于myNameSpace命名空间下,程序集名称为myDll,我们只需将myDll.dll拷贝到Bin目录下,并在站点的 web.config 文件 system.web 结点下创建 httpModules 结点:
<system.web> <httpModules> <add name="CustomModuleName" type="myNameSpace.ModuleDemo, myDll"/> </httpModules></system.web>
type属性由分号“,”分为两部分,前面是命名空间及类名,也就是类型名;后面是程序集名。如果我们将代码创建在App_Code目录中,则不需要再指定程序集名。
name属性由我们自己命名,不一定与类名相同,此处我将它命名为“CustomModuleName”。我们可以通过应用程序(Httpapplication)的Modules属性获取HttpModuleCollection集合,然后通过name属性,进一步获取HttpModule对象。
通过name属性,我们还可以在global.asax中文件中编写自定义HttpModule暴露出的事件的处理程序,它采用的格式是:void ModuleName_EventName(object sender, EventArgs e)。我们将在后面做更详细介绍。
Asp.Net 内置的 Http Modules
下面这张表格列出了C:/WINDOWS/Microsoft.NET/Framework/ v2.0.50727/CONFIG下的Web.Config中的 Asp.Net 内置的Http Modules 及其主要作用。
名称 | 类型 | 功能 |
OutputCache | System.Web.Caching.OutputCacheModule | 页面级输出缓存 |
Session | System.Web.SessionState.SessionStateModule | Session状态管理 |
WindowsAuthentication | System.Web.Security.WindowsAuthenticationModule | 用集成Windows身份验证进行客户端验证 |
FormsAuthentication | System.Web.Security.FormsAuthenticationModule | 用基于Cookie的窗体身份验证进行客户端身份验证 |
PassportAuthentication | System.Web.Security.PassportAuthenticationModule | 用MS护照进行客户身份验证 |
RoleManager | System.Web.Security.RoleManagerModule | 管理当前用户角色 |
UrlAuthorization | System.Web.Security.UrlAuthorizationModule | 判断用户是否被授权访问某一URL |
FileAuthorization | System.Web.Security.FileAuthorizationModule | 判断用户是否被授权访问某一资源 |
AnonymousIdentification | System.Web.Security.AnonymousIdentificationModule | 管理Asp.Net应用程序中的匿名访问 |
PRofile | System.Web.Profile.ProfileModule | 管理用户档案文件的创立 及相关事件 |
ErrorHandlerModule | System.Web.Mobile.ErrorHandlerModule | 捕捉异常,格式化错误提示字符,传递给客户端程序 |
我们将在后面用编程的方式来查看它。
IHttpModule接口
看了这么多理论知识,本节将开始动手写点程序,实现自己的Http Module。我们首先需要看下IHttpModule 接口,它包括下面两个方法:
public void Init(HttpApplication context);public void Dispose();
Init():这个方法接受一个HttpApplication对象,HttpApplication代表了当前的应用程序,我们需要在这个方法内注册 HttpApplication对象暴露给客户端的事件。可见,这个方法仅仅是用来对事件进行注册,而实际的事件处理程序,需要我们另外写方法。
整个过程很好理解:
NOTE:如果你不了解事件注册等相关内容,请参阅C#中的委托与事件一文。
Dispose():它可以在进行垃圾回收之前进行一些清理工作。
综上所述:实现一个 IHttpModule 的模板一般是这样的:
public class ModuleDemo:IHttpModule{ public void Init(HttpApplication context) { // 注册HttpApplication应用程序 BeginRequest 事件 // 也可以是其他任何HttpApplication暴露出的事件 context.BeginRequest += new EventHandler(context_BeginRequest); } void context_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context; // 做些实际的工作,HttpContext对象都获得了,剩下的基本可以自由发挥了 } public void Dispose() { }}
通过Http Module向Http请求输出流中写入文字
本例中,我们仅用BeginRequest事件和 EndRequest 事件对 Http Module 的使用作以说明。我们通过这个范例,了解 Http Module 基本的使用方法。
首先,请创建一个新的站点,在App_Code目录中添加类文件: ModuleDemo.cs:
public class ModuleDemo:IHttpModule{ // Init方法仅用于给期望的事件注册方法 public void Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); context.EndRequest += new EventHandler(context_EndRequest); } // 处理BeginRequest 事件的实际代码 void context_BeginRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context; context.Response.Write("<h1 style='color:#00f'>来自HttpModule 的处理,请求到达</h1><hr>"); } // 处理EndRequest 事件的实际代码 void context_EndRequest(object sender, EventArgs e) { HttpApplication application = (HttpApplication)sender; HttpContext context = application.Context; context.Response.Write("<hr><h1 style='color:#f00'>来自HttpModule的处理,请求结束</h1>"); } public void Dispose() { }}
上面的代码很简单,它注册了 HttpApplication实例的 BeginRequest 事件
新闻热点
疑难解答