HttpModule的一个小问题

      通过自定义HttpModule我们可以实现在应用程序级做一些响应事件。但是有一个疑问困扰着我,就是是自定义HttpModule注册的事件先响应还是框架里原有的HttpModule注册的事件先响应。于是昨晚写了一段代码进行测试。

      思路是这样子的,通过在应用程序启用Form验证,拒绝所有用户对页面的访问。

<authentication mode="Forms">
      <forms loginUrl="login.aspx"></forms>

    </authentication>
    <authorization>
      <deny users="*"/>
    </authorization>

     自定义个HttpModule,在其中注册AuthenticateRequest,代码如下:

public void Init(HttpApplication context)
{

context.AuthenticateRequest
+= new EventHandler(context_AuthenticateRequest);

}

void context_AuthenticateRequest(object sender, EventArgs e)
{
HttpApplication application
= sender as HttpApplication;
application.Response.Write(
"验证");//自定义的HttpModule事件发生在系统的之前
application.Server.Transfer("~/Default2.aspx");
}

     发现当对Default.aspx页进行请求的时候,这样能绕过Form验证,于是昨晚睡觉前就下了一个结论,自定义的HttpModule所注册的事件先于框架的HttpModule所注册的事件。就在刚才打算写博客备忘的时候,发现自己疏忽了一点,我之所以有那个错误的结论是认为当我们的请求没有通过Form验证的时候会直接跳转到login.aspx,在AuthenticateRequest事件之后的事件是不会触发的。如果会触发,那也就存在一个可能在验证不通过后,接下来再触发自定义的AuthenticateRequest事件实现了跳转,进而不会跳转到login.aspx。为了验证自己的这个推论,我再注册了一个事件

View Code
1 context.EndRequest += new EventHandler(context_EndRequest);
2 void context_EndRequest(object sender, EventArgs e)
3 {
4 HttpApplication application = sender as HttpApplication;application.Response.Write("end request");
5 }

      发现当跳转到login.aspx页面的时候,end request会输出,于是得出一个结论:AuthenticateRequest事件进行验证的时候,验证失败还是会执行接下来的事件的(这其实是Redirect和Transfer的区别造成的)。因此昨晚下的那个结论有漏洞。那个是怎么确定是系统定义的在前还是自己定义的在前呢?应该通过Reflector来看代码就知道了,Reflector的相关代码如下:

private void InitModules()
{
this._moduleCollection = RuntimeConfig.GetAppConfig().HttpModules.CreateModules();
this.InitModulesCommon();
}

private void InitModulesCommon()
{
int count = this._moduleCollection.Count;
for (int i = 0; i < count; i++)
{
this._currentModuleCollectionKey = this._moduleCollection.GetKey(i);
this._moduleCollection[i].Init(this);
}
this._currentModuleCollectionKey = null;
this.InitAppLevelCulture();
}



     第一个代码片段是通过config的配置,反射创建各个HttpModule,并对HttpApplication的HttpModule集合进行赋值,第二个代码片段就是对HttpApplication的moduleCollection进行初始化,也就是调用Init方法注册事件,因此现在问题就纠结在HttpApplication的moduleCollection集合里面是自定义的MyHttpModule在前面还是System.Web.Security.FormsAuthenticationModule在前,因为我们知道事件注册的先后顺序和事件触发的先后顺序是一致的。接下来通过对HttpApplication的moduleCollection进行遍历

foreach (string item in application.Modules.AllKeys)
{
application.Response.Write(item
+ "<br>");
}

得出的结果如下:

View Code
1 OutputCache
2 Session
3 WindowsAuthentication
4 FormsAuthentication
5 PassportAuthentication
6 RoleManager
7 UrlAuthorization
8 FileAuthorization
9 AnonymousIdentification
10 Profile
11 ErrorHandlerModule
12 ServiceModel
13 MyHttpModule
14 ScriptModule
15 DefaultAuthentication

      貌似顺序和在config中 <httpModules>借的注册顺序一致,为了验证这个结论我将这个节改为:

  <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   <add name="MyHttpModule" type="HttpModuleDemo.MyHttpModule,HttpModuleDemo" />

       再次运行程序输出结果果然是MyHttpModule在ScriptModule之后,我不放心,再添加了一个MyHttpModule2进行验证,结果还是一样。因此可以得出结论,HttpApplication中的moduleCollection的顺序和config的顺序一致,这也就意味着,在config配置中的顺序影响着事件触发时的执行顺序。

       那么如果我先将FormsAuthentication Remove掉,接下来再添加,就像下面的情况:      

<remove name="FormsAuthentication"/>
<add name="MyHttpModule2" type="HttpModuleDemo.MyHttpModule2,HttpModuleDemo" />
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="MyHttpModule" type="HttpModuleDemo.MyHttpModule,HttpModuleDemo" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />

输出如下:

View Code
1 OutputCache
2 Session
3 WindowsAuthentication
4 FormsAuthentication
5 PassportAuthentication
6 RoleManager
7 UrlAuthorization
8 FileAuthorization
9 AnonymousIdentification
10 Profile
11 ErrorHandlerModule
12 ServiceModel
13 MyHttpModule2
14 ScriptModule
15 MyHttpModule
16 DefaultAuthentication

     可以发现FormsAuthentication的输出顺序还是不变。

     因此我得出以下的结论:自定义的HttpModule对于所注册的HttpApplication的事件的执行顺序,是框架的HttpModule先执行,自定义的和其在config的配置顺序是一致的。对框架的HttpModule我们对其进行Remove之后再添加对其不影响。

posted @ 2011-03-25 11:51  雁北飞  阅读(519)  评论(0编辑  收藏  举报