`
北极的。鱼
  • 浏览: 160949 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】Http Module 介绍

阅读更多

【转自   http://www.tracefact.net/Asp-Net/Introduction-to-Http-Module.aspx

引言

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对象暴露给客户端的事件。可见,这个方法仅仅是用来对事件进行注册,而实际的事件处理程序,需要我们另外写方法。

整个过程很好理解:

  1. 当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。
  2. 在创建Module实例的时候会调用Module的Init()方法。
  3. 在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。
  4. HttpApplication在其应用程序周期中触发各类事件。
  5. 触发事件的时候调用Module在其Init()方法中注册过的方法。

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 事件 和 EndRequest事件,事件处理方法的作用仅仅是在http请求开始和结束的时候,给http请求的输入流中分别写入不同的内容。

接下来在 Web.config 的 System.web 结点中写入以下内容:

<system.web>
    <httpModules>
       <add name="MyModule" type="ModuleDemo" />
    </httpModules>
</system.web>

然后,打开建立站点时自动创建的 Default.aspx文件,在里面打几个字,为了做区分,我输入的是:位于.aspx页面上的文字。然后,我们在浏览器中打开它,应该会看到像这样:

然后我们再新建一个 Default2.aspx,在浏览器中浏览,可以看到,两个页面的效果相同。这说明对于不同的两个文件,http Module都起了作用,可见它确实是位于应用程序级,而非页面级。

现在,我们再打开站点中的一张图片文件,发现显示出的是一个红叉叉,为什呢?因为Http Module 针对是http 请求,而不是某个或某一类文件,所以当请求一张图片的时候,我们编写的http Module依然会起作用,将文字插入到二进制图片中,破坏了文件格式,自然只能显示红叉叉了。

NOTE: 如果你发现你的图片显示正常,请不要惊讶,事情是这样的:回想一下第一节我们讨论到的,对于图片文件,由IIS直接处理,并不会交由aspnet_isapi.dll,所以,Module无法捕获对于图片类型文件的请求。解决方法就是在IIS中进行设置一下。
    这里需要提请注意的是:如果你使用Vs2005自带的Local Server,那么你无需对IIS进行设置,所有的不论图片还是任何文件类型,都会交由aspnet_isapi.dll处理。

遍历Http Module集合

现在,我们通过遍历 HttpModuleCollection 集合来查看注册给应用程序的所有 Http Module 的名称。

新建一个文件 RegisteredModules.aspx,在代码后置文件中添加如下方法:

private string ShowModules() 
{
    HttpApplication app = Context.ApplicationInstance; //获取当前上下文的HttpApplication环境
    HttpModuleCollection moduleCollection = app.Modules; //获取所有Module集合

    // 获取所有的 Module 名称
    string[] moduleNames = moduleCollection.AllKeys;

    System.Text.StringBuilder results = new System.Text.StringBuilder();    //遍历结果集

    foreach (string name in moduleNames) 
    {
       // 获得Module名称
       results.Append("<b style='color:#800800'>名称:" + name + "</b><br />");
        // 获得Module类型
       results.Append("类型:" + moduleCollection[name].ToString() + "<br />"); 
    }
    return results.ToString();
}

然后在Page_Load方法中输出一下:

 

protected void Page_Load(object sender, EventArgs e)
{
    Response.Write(ShowModules());
}

我们应该可以看到下面这样的画面:

与之前列出的那张表格比较一下,可以看出是几乎完全一致的(多了一个DefaultAuthentication)。另外注意上图的倒数第四行,那不是我们自己定义的Module么?name为MyModule,类型为ModuleDemo。

Global.asax文件与 Http Module

早在asp时代,大家就知道这个文件了。它主要用于放置对于 应用程序事件或者 Session事件的响应程序。大家熟悉的有Application_Start、Application_End、Session_Start、Session_End 等。

在asp.net中,Glabal不仅可以注册应用程序和Session事件,还可以注册Http Module暴露出的事件;不仅可以注册系统Module的事件,也可以注册我们自己义的Module暴露出的事件。在具体介绍之前,这里需要首先注意两点:

  1. 在每处理一个Http请求时,应用程序事件都会触发一遍,但是Application_Start和 Application_End 例外,它仅在第一个资源文件被访问时被触发。
  2. Http Module无法注册和响应Session事件,对于Session_Start 和 Session_End,只能通过Glabal.asax来处理。

好了,我们现在修改之前 ModuleDemo 范例程序,给它像下面这样给它添加一个事件(为了使程序简洁一些,我做了简化):

public class ModuleDemo : IHttpModule
{
    // 声明一个事件
    public event EventHandler ExposedEvent;

    // Init方法仅用于给期望的事件注册方法
    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }

    // 处理BeginRequest 事件的实际代码
    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpApplication application = (HttpApplication)sender;
        HttpContext context = application.Context;
        context.Response.Write("<h3 style='color:#00f'>来自HttpModule的处理,请求到达</h3><hr>");

        OnExposedEvent(new EventArgs()); // 调用方法
    }

    protected override void OnExposedEvent(EventArgs e)
    {
        if (ExposedEvent != null) // 如果Global中有注册
            ExposedEvent(this, e);   // 调用注册了的方法
    }

    public void Dispose()
    {
    }
}

接下来,我们在站点中创建一个 Global.asax 文件,在里面添加如下代码,注意到格式是:void 模块名_事件名(object sender, EventArgs e)。

void MyModule_ExposedEvent(object sender, EventArgs e)
{
     Response.Write("<h3 style='color:#800800'>来自 Global.asax 的文字</h2>");
}

现在,我们打开之前的页面,应该可以见到这样,可见,我们成功的将 Glabal.asax文件与我们自己定义的Http Module所暴露出的事件 ExposedEvent 联系到了一起:

总结

本文简单地介绍了什么是Http Module。我们首先了解了Http Module的作用,然后查看了Asp.Net 内置的Module,接着我们介绍了IHttpModule接口,并通过了一个简单的范例实现了此接口,最后我们讨论了 Http Module与 Global.asax 文件的联系。

本文仅仅是对IHttpModule作以简单介绍,对其更多的实际应用,会在后续文章中补充。

希望这篇文章能给你带来帮助!

分享到:
评论

相关推荐

    添加了http_image_filter_module模块的Nginx

    本文将详细介绍`http_image_filter_module`模块及其在Nginx 1.15.9(Windows 64位)中的应用。 `http_image_filter_module`模块是Nginx内置的一个图像处理模块,它允许我们在服务器端对请求的图像进行实时处理,如...

    SINAMICS G120, Power Module PM230 FSA, FSB, FSC[手册].pdf

    知识点一:SINAMICS G120驱动器的介绍 SINAMICS G120是西门子公司生产的一款变频器,属于其SINAMICS系列。它广泛应用于工业驱动控制领域,适用于各种不同的驱动任务。该变频器系列支持模块化设计,可根据用户需求...

    nginx-rtmp-module-master

    **RTMP 协议介绍** RTMP 是一种专为音视频数据流设计的网络传输协议,广泛应用于在线直播和点播服务。它允许客户端与服务器之间建立持久连接,实时传输音频、视频和控制信息。尽管 RTMP 并非最新的协议,但由于其...

    Vision Development Module(视觉开发模块),这个是NI视觉所有的图像处理函数库,包提供在LabVIEW编

    在本示例中,我们将介绍如何使用VDM进行圆形拟合,具体步骤如下: 1. **图像采集**: 首先通过摄像头捕获包含圆形的目标图像。 2. **预处理**: 对原始图像进行灰度化处理,并使用阈值分割去除噪声干扰。 3. **边缘...

    POINTBlock dc 8 Input/8 Output Module.pdf

    本文档介绍的是POINTBlock dc 8 Input/8 Output Module,它是一种DIN导轨安装的设备,具有集成的DeviceNet通信接口、8个输入和8个输出、可拆卸的终端以及Point Bus扩展端口。该模块利用DeviceNet连接供电的24Vdc为非...

    NI Vision 8.6 Development Module keygen

    通过以上介绍,我们可以看到,NI Vision 8.6不仅是一个强大的视觉开发工具,而且是一个完整的解决方案,涵盖了从开发到部署的全过程。无论是新手还是经验丰富的开发者,都能从中找到适合自己的工具和功能,实现高效...

    AN_136 Hi Speed Mini Module EEPROM Disaster Recovery[1]

    FTDI Hi-Speed Mini Module介绍 FTDI(Future Technology Devices International Limited)是一家在USB接口技术领域内领先的公司,其产品广泛应用于各种电子设备的设计与开发。Hi-Speed Mini Modules是FTDI为帮助...

    BEC商务英语Module3PPT教学课件.pptx

    【BEC商务英语Module3PPT教学课件】是一份专为学习商务英语设计的专业课件,涵盖了与公司介绍和商务活动相关的重要词汇和表达。本课件的主要目标是帮助学习者熟悉商务环境中的核心词汇,掌握如何介绍公司的基本概况...

    package.json中main,module,exports三种方式的使用,自定义入口文件index.js

    - `README.md`:项目的基本说明文档,通常包含项目介绍、安装和使用方法等信息。 - `src`:源代码目录,通常包含Vue组件、路由、样式和其他应用逻辑。 综上所述,理解和正确使用`package.json`中的`main`、`module`...

    OV5640_Camera_Module_Hardware_Application_Notes_R1.0英文手册.pdf

    这部分详细介绍了OV5640摄像头模块的硬件设计,包括模块的物理布局、电气特性、信号处理和电源管理等方面。它涵盖了必要的组件选择、布局布线策略以及优化模块性能的关键要素,以确保与不同主机系统的兼容性和高效...

    nginx_upload_module 加lua 实现上传

    这篇博文(链接:)可能详细介绍了如何在Nginx中集成`nginx_upload_module`与Lua,以实现高效且可控的文件上传方案。 首先,我们需要了解`nginx_upload_module`。这是一个非官方的Nginx模块,它提供了处理HTTP POST...

    nginx-rtmp-module.rar

    Nginx RTMP 模块默认并不提供详细日志,但可以通过编写自定义脚本或使用如 nginx-rtmp-module-stats 这样的扩展来获取更详细的流统计信息。 8. **安全性考虑** 为了保护流媒体内容和服务器安全,应考虑使用 SSL/...

    Python Module of the Week及配套代码

    "Python Module of the Week"(POTW)是一系列教程,专注于介绍Python标准库中的不同模块,帮助开发者深入了解并利用这些模块提升编程效率。每个星期,这个项目都会挑选一个Python模块进行深入讲解,涵盖其主要功能...

    The Linux Kernel Module Programming Guide 2.6 中英文對照版

    这本书详尽地介绍了如何编写、调试和理解Linux内核模块,是学习这一领域的必备参考资料。文档提供了中文和英文双语版本,方便不同语言背景的读者对照学习。 Linux内核模块是Linux操作系统中一种灵活的机制,允许...

    3.5inch_SPI_Module_ILI9488_MSP3520_V1.1.7z

    本文将深入探讨标题为"3.5inch_SPI_Module_ILI9488_MSP3520_V1.1.7z"的资源包,该资源包主要涉及3.5英寸SPI接口的TFT(薄膜晶体管)显示屏及其控制器MSP3520的使用。 1. SPI接口介绍: SPI(Serial Peripheral ...

    The kS3-module algebra structures on M3(k)

    从1976年Beattie首次介绍Hopf代数作用的概念,到后来数学家们对这些理论的进一步研究和成果总结,例如Blattner和Montgomery对Hopf模代数的对偶定理的推广,以及Montgomery在1993年对之前研究的系统性总结。...

    Python库 | wolk-gateway-module-1.0.1.tar.gz

    2. **协议适配**:由于物联网设备使用的通信协议多种多样,如MQTT、CoAP、HTTP等,`wolk-gateway-module`支持多种协议的转换,确保设备之间的有效通信。 3. **数据处理**:库内包含数据解析和封装的功能,能够将...

    nginx插件iconv

    6. **配置Nginx使用iconv模块**:在Nginx的配置文件(通常是`nginx.conf`)中,添加`load_module`指令来加载`iconv`模块的`.so`文件,例如:`load_module modules/ngx_http_iconv_module.so;`。 7. **重启Nginx**:...

    Module_BMS_Integration.pptx

    本文档由Juniper Networks公司在2014年发布,主要介绍了一个名为Contrail的新系统如何与ToR(Top-of-Rack)交换机进行集成,以提供高效、可扩展的服务。 Contrail BMS(bare metal service,裸金属服务)集成的核心...

Global site tag (gtag.js) - Google Analytics