65.9K
CodeProject 正在变化。 阅读更多。
Home

Asp.net HTTP 模块

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.19/5 (9投票s)

2009年1月13日

CPOL

7分钟阅读

viewsIcon

67378

HTTP 模块用于拦截 HTTP 请求,以便根据需要修改或利用基于 HTTP 的请求。

ASP.NET HTTP 模块

HTTP 模块

HTTP 模块用于拦截 HTTP 请求,以便根据需要进行修改或利用基于 HTTP 的请求,例如身份验证、授权、会话/状态管理、日志记录、修改响应、URL 重写、错误处理、缓存……。

HTTP 模块在 HTTP 处理程序执行之前和之后被激活/调用/触发。

HTTP 模块现在是 ASP.NET 框架的组成部分,并且得到了大量使用,因为它能够控制请求并允许开发人员根据用户需求以自定义方式生成响应。Web 开发就是处理从客户端到服务器的请求以及从服务器到客户端的响应。

当任何请求到达 Web 服务器时,该请求会经过不同的阶段,最后为客户端生成响应。

HTTP 模块是基于 .Net 的组件/插件,通过实现 .Net 的 System.Web.IHTTPModule 接口进行编程。

HTTP 模块背景

在 HTTP 模块之前,Web 开发人员/程序员通常会实现 Internet Server Application Programming Interface (ISAPI) 过滤器,就像我一样(希望面试官当时会问我 ISAPI 的相关问题,那样我就可以告诉他了(:D)),开个玩笑。

顾名思义,ISAPI 是一个基于 Web 服务器的 API,用于管理到达 Web 服务器的请求并生成响应。ISAPI 基于 Web 服务器 (IIS),而 NSAPI 是基于 Netscape 的 Web 服务器 API。

ISAPI 基于 win32 DLL 并在非托管代码 C/C++ 中进行编程,这有些痛苦(: $),而且由于非托管代码,其可靠性、可伸缩性不如 .Net 框架下使用托管代码编写的 HTTP 模块,实现起来也相当复杂。希望您明白为什么 ISAPI 过滤器被 HTTP 模块取代了(;))。

Asp.net 请求会经过 HTTP 模块事件,就像(油流过管道,管道中有一些过滤器来精炼油)一样。

HTTP 模块事件

每个 HTTP 模块都必须实现 IHTTPModule 接口的以下两个方法:

Init:为基于 HTTP 的应用程序注册/初始化 HTTP 模块的事件处理程序。

Dispose:执行清理代码,即释放资源、从内存中移除对象以及释放显式使用的其他此类资源。

以下是事件列表及其简要描述:

BeginRequest:每当有基于 asp.net 的请求发送到 Web 服务器时,都会触发此事件。如果您需要在请求开始时执行操作,例如修改横幅显示、记录 HTTP 标头信息、获取/设置区域性、使用 Response.Filter 根据需要为浏览器生成响应。

AuthenticateRequest:如果您想检查请求的身份验证,即请求是否来自已通过身份验证的用户,或者说您想实现自定义身份验证方案。例如,查找请求用户的凭据是否在数据库中得到验证。

AuthorizeRequest:此方法专门用于实现授权机制,即已通过身份验证的用户/请求在该特定应用程序中拥有哪些权限/权利/访问权限。例如,用户是否可以访问该网站的所有页面,或者是否有权创建文件,或者是否可以访问报告页面,等等。

ResolveRequestCache:此事件确定页面是否从输出缓存提供。如果您想编写自己的缓存模块(例如,构建基于文件的缓存而不是内存缓存),请同步此事件以确定是否从缓存提供页面。

AcquireRequestState:从状态存储检索会话状态。如果您想构建自己的状态管理模块,请同步此事件以从您的状态存储中获取会话状态。

PreRequestHandlerExecute:此事件在 HTTP 处理程序执行之前发生。

PostRequestHandlerExecute:此事件在 HTTP 处理程序执行之后发生。

ReleaseRequestState:会话状态将存储回状态存储。如果您正在构建自定义会话状态模块,则必须将您的状态存储回您的状态存储。

UpdateRequestCache:此事件将输出写入输出缓存。如果您正在构建自定义缓存模块,则必须将输出写回您的缓存。

Error:当应用程序中发生任何异常(未处理的错误)时,始终会发生此事件。此事件专门用于处理或记录该 Web 应用程序的错误消息。(在 ELMAH(错误日志模块和处理程序)之类的应用程序中大量使用)。您可以通过以下链接详细了解 ELMAH:http://dotnetslackers.com/articles/aspnet/ErrorLoggingModulesAndHandlers.aspx

EndRequest:请求已完成。您可能想要构建一个调试模块,该模块在整个请求过程中收集信息,然后将信息写入页面。

通过以上事件列表,您一定想知道 Global.asax 和 HTTP 模块之间的区别,因为 Global.asax 的某些事件非常相似,所以让我告诉您 Global.asax 和 HTTP 模块的区别(这是另一个常见的面试问题)。

但是您需要在“Init”方法中显式注册/初始化这些事件;以下是一个实现几个事件的 IHTTPModule 的示例代码。

"kwd">using System;
"kwd">using System.Web;
"kwd">using System.Collections;

"kwd">public class HelloWorldModule : IHttpModule
{
    "kwd">public String ModuleName
    {
        "kwd">get { "kwd">return "st">"HelloWorldModule"; }
    }

    "cmt">// In the Init function, register for HttpApplication 
    // events by adding your handlers.
    "kwd">public void Init(HttpApplication application)
    {
         application.BeginRequest += ("kwd">new EventHandler("kwd">this.Application_BeginRequest));
         application.EndRequest += ("kwd">new EventHandler("kwd">this.Application_EndRequest));

    }

    "cmt">// Your BeginRequest event handler.

    "kwd">private void Application_BeginRequest(Object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        context.Response.Write("st">"&lt;h1><font color=red>HelloWorldModule: Beginning of Request</font></h1><hr>");
    }

    "cmt">// Your EndRequest event handler.

    "kwd">private void Application_EndRequest(Object source, EventArgs e)
    {
        HttpApplication application = (HttpApplication)source;
        HttpContext context = application.Context;
        context.Response.Write("st">"&lt;hr><h1><font color=red>HelloWorldModule: End of Request</font></h1>");
    }
    "kwd">public void Dispose()
    {
    }
}

参考:msdn

HTTP 模块与 Global.asax

 

1. HTTP 模块是可插入组件,因此可以用于其他 Web 应用程序,也可以用于其他服务器或同一服务器上的其他应用程序,而 Global.asax 不能。

2. 根据请求的生命周期,请求首先经过 HTTP 模块,然后经过 Global.asax。

3. 以下是 Global.asax 支持但 HTTP 模块不幸不支持的事件列表:

  1. Application_OnStart
    当第一个请求通过 Web 应用程序时,会引发此事件。

  2. Application_OnEnd
    在应用程序即将终止之前,会引发此事件。

  3. Session_OnStart
    当用户会话的第一个请求到来时,会引发此事件。

  4. Session_OnEnd
    当会话被放弃或过期时,会引发此事件。

在这里,我想分享一下我的一次面试经历,但这次是关于我朋友的面试,他为此做了准备/得到了我的帮助或指导。无论如何,在我帮助他准备 asp.net 技术面试时,我问他:“告诉我,会话何时开始?”他回答:“很简单,当用户从登录页面登录时”,我说是的!假设网站没有登录页面,并且可以被匿名用户访问,那么会话永远不会开始,Global.asax 的 Session_OnStart 事件也不会触发,对吗?他回答:“当然”,我忍不住笑了;如果他没有经验或经验较少,我可能不会笑,但他有 4 年以上的经验。无论如何,第二天他去面试时,面试官问了他同样的问题,他笑了,说:“如果您认为我会说当用户登录时会话_Onstart 事件会触发,那么您就错了。(他们也笑了)。

无论如何,人们通常会说,或者根据书本以简单的方式告诉读者,会话是基于用户的,不对!会话实际上是基于浏览器的。无论如何,不应离题太远。

注册 HTTP 模块

以下是注册/添加 HTTP 模块的示例:

  <httpModules>    <add type="ClassName, AssemblyName" name="ModuleName" />  <httpModules>

 

以下是从 Web 应用程序中删除 HTTP 模块的一般示例:

 

  <httpModules>    <remove name="ModuleName" />  <httpModules>

 

所有代码都应该放在 web.config 或 machine.config 中。

以下是默认在 machine.config 或 web.config 中定义的模块列表。($WINDOWS$\Microsoft.NET\Framework\$VERSION$\CONFIG\ CONFIG Files

 

<httpModules><add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/><add name="Session" type="System.Web.SessionState.SessionStateModule"/><add name="WindowsAuthentication" ="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"/><add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule"/><add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule"/><add name="Profile" type="System.Web.Profile.ProfileModule"/><add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/><add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/></httpModules>

性能

您可以通过删除 machine.config 文件中默认注册(但未使用的)HTTP 模块来提高应用程序的性能,因为这些模块会在每次请求时被不必要地激活/调用/触发。您可以使用 <remove …> 来删除,例如:

 

<httpModules>    <!-- Remove unnecessary Http Modules for faster pipeline -->     <remove name="Session" />      <remove name="WindowsAuthentication" />     <remove name="PassportAuthentication" />     <remove name="AnonymousIdentification" />     <remove name="UrlAuthorization" />

 

     <remove name="FileAuthorization" />     <remove name="OutputCache" />     <remove name="RoleManager" />     <remove name="Profile" />     <remove name="ErrorHandlerModule" />     <remove name="ServiceModel" />  </httpModules>

但在实施/应用之前,请确保您没有使用它们。如果您正在使用其中任何一个,您可以将其从现有列表中排除。

结论

HTTP 模块非常容易理解,并且由于其众多的事件而非常灵活。HTTP 模块与整个应用程序集成,每个请求都经过 HTTP 模块。因此,应该非常小心地实现 HTTP 模块。在实施解决方案之前,花时间完全理解其优点、缺点、实现和概念。

为了更详细地了解 HTTP 模块及其真实示例的实现,我建议您访问以下链接:

 

推荐链接

有关 URL 重定向示例,请点击此处

有关基于安全性的示例,请点击此处

有关基于 IP 的安全性示例,请点击此处

有关错误管理器示例,请点击此处

有关视频,请点击此处和 此处

© . All rights reserved.