天天看点

HttpHandler与HttpModule讲解

实现HttpHandler

HttpHandler对象必须实现IHttpHandler接口,在HttpApplication对象转交要求至HttpHandler对象时会调用此接口中的init函数,下面是一个HelloHandler类的程序。

using System;
using System.Web;
using System.Web.SessionState;

namespace c64.HttpHandler
{
	public class HelloHandler : IHttpHandler,IRequiresSessionState
	{		
		#region IHttpHandler Members

		public void ProcessRequest(HttpContext context)
		{
			context.Response.ContentType = "text/html";
			context.Response.Write("<html>");
			context.Response.Write("<body>");
			context.Response.Write("<B>Response By HelloHandler</B>");
			context.Response.Write("</body");
			context.Response.Write("</html>");
		}

		public bool IsReusable
		{
			get
			{				
				return true;
			}
		}

		#endregion
	}
}
           

挂载这个HttpHandler对象的方法有两种,一种是直接修改.NET Framework目录中的machine.config文件,这样做将本机上所有的asp.net程序挂载此HttpHandler对象,另一中方式是修改虚拟目录中的web.config文件,此方案只会影响该虚拟目录中的asp.net程序。此处采用第二种方式,请于web.config文件中加入下面的叙述。

<httpHandlers>

   <add verb="*" path=".ho" type="c64.HttpHandler.HelloHandler,HelloHanlder"/>

</httpHanlders>

path部分的设定是告知HttpApplication对象此HttpHandler对象时对应那一种文件扩展名,type设定的前段是类的名称与namespace,后段是Assembly文件名。除此之外,要让aspnet_isapi.dll接受.ho文件的要求,还得在IIS中设定虚拟目录的内容设定扩展名对应表。

HttpHandler与HttpModule讲解

关于Session

默认情况下,当HttpHandler对象被调用时Session对象并未初始化成可用状态,倘若HttpHandler对象须要使用到Session对象时,必须同时实现IRequiresSessionState接口,此接口只是识别用途,无须实现任何的方法,下面的程序实现了IRequiresSessionState接口的HelloHandler类源代码。

using System;
using System.Web;
using System.Web.SessionState;

namespace c64.HttpHandler
{
	public class HelloHandler : IHttpHandler,IRequiresSessionState
	{		
		#region IHttpHandler Members

		public void ProcessRequest(HttpContext context)
		{
			context.Response.ContentType = "text/html";
			context.Response.Write("<html>");
			context.Response.Write("<body>");
			context.Response.Write("<B>Response By HelloHandler</B>");
			string user = (string)context.Session["USER"];
			if(user != null && user.Length > 0)
                context.Response.Write(user);
			context.Response.Write("</body");
			context.Response.Write("</html>");
		}

		public bool IsReusable
		{
			get
			{				
				return true;
			}
		}

		#endregion
	}
}
           

要测试这个程序,我们可以在WebForm上放置一个按钮,当用户按下后存放一个字符串到Session["USER"]中,接着要求.ho的文件就可以看到结果。

实现HttpModule

与HttpHandler对象的加载时机不同,HttpModule对象是在HttpApplication对象初始化时就一并载入的,这个时机是在本机开机后第一个用户访问此虚拟目录时。设计人员撰写HttpModule对象的机会不多,甚至比撰写HttpHandler对象的机会还少。下面撰写一个HelloModule对象来示范如何撰写HttpModule对象。

using System;
using System.Web;
using System.Web.SessionState;

namespace HttpModule
{
	public class HelloModule : IHttpModule,IRequiresSessionState
	{		
		#region IHttpModule Members

		public void Init(HttpApplication context)
		{
			context.Application["HELLO"] = "I am Hello Module!";
			context.Application[GetHashCode().ToString()] = 123;
		}

		public void Dispose()
		{			
		}

		#endregion
	}
}
           

这个HelloModule对象只是很简单地在Application的State对象中放入一个字符串,与加载HttpHandler对象的方式相同,我们可以修改mechine.config文件或是虚拟目录内的web.config文件来载入它,此处采用第二种方案,请于web.config文件中放入以下的叙述。

<httpModules>

   <add name ="HelloModule"  type="HttpModule.HttpModule,HelloModule"/>

</httpModules>

要测试这个HelloModule对象,只须与WebForm上放置一个按钮,当用户按下后由Application State对象中取出由HelloModule对象所放入的字符串即可,下图是HelloModule对象的执行结果。

IHttpModule实现权限控制

总所周知实现一个系统权限管理模块有很多种实现方式,在这里和大家探讨下管道模型实现权限管理模块。

ASP.NET Framework处理一个Http Request的流程:

 HttpRequest-->inetinfo.exe-->ASPNET_ISAPI.dll-->ASPNET_WP.exe-->HttpRuntime-->HttpApplication Factory-->HttpApplication-->HttpModule-->HttpHandler Factory-->HttpHandler-->HttpHandler.ProcessRequest()

ASP.NET请求处理过程是基于管道模型的,这个管道模型是由多个HttpModule和HttpHandler组成,ASP.NET把http请求依次传递给管道中各个HttpModule,最终被HttpHandler处理,处理完成后,再次经过管道中的HTTP模块,把结果返回给客户端。

我们可以在每个HttpModule中都可以干预请求的处理过程。

注意:在http请求的处理过程中,只能调用一个HttpHandler,但可以调用多个HttpModule。

实现权限控制的思路:

可以利用这个特点对页面访问进行权限控制,当用户请求页面时,可以在HttpModule中进行判断,如果不是指定角色,就拒绝其访问

先了解下IHttpModule这个接口:

   IHttpModule向实现类提供模块初始化和处置事件。

IHttpModule包含兩個方法:

public void Init(HttpApplication context);

public void Dispose();

Init():这个方法接受一个HttpApplication对象,HttpApplication代表了当前的应用程序,我们需要在这个方法内注册 HttpApplication对象暴露给客户端的事件。可见,这个方法仅仅是用来对事件进行注册,而实际的事件处理程序,需要我们另外写方法。

整个过程很好理解:

1.       当站点第一个资源被访问的时候,Asp.Net会创建HttpApplication类的实例,它代表着站点应用程序,同时会创建所有在Web.Config中注册过的Module实例。

2.       在创建Module实例的时候会调用Modul的Init()方法。

3.       在Init()方法内,对想要作出响应的HttpApplication暴露出的事件进行注册。(仅仅进行方法的简单注册,实际的方法需要另写)。

4.       HttpApplication在其应用程序周期中触发各类事件。

5.       触发事件的时候调用Module在其Init()方法中注册过的方法。

Dispose():它可以在进行垃圾回收之前进行一些清理工作。

实现步骤:

先创建一个登陆页面Login.aspx;主要代码:

 protected void btnLogin_Click(object sender, EventArgs e)

        {

         if (this.txtUserName.Text.Trim()!="" && this.txtPwd.Text.Trim()!="")

          {

            string url = Request.QueryString["ReturnUrl"];

            //添加身份验证票证

            FormsAuthentication.RedirectFromLoginPage(this.txtUserName.Text, false);

            if (url!=null)

            {

                Response.Redirect(url);

            }

            Response.Redirect("Index.aspx");

        }

    }

创建一个类实现IHttpModule接口:Test.cs

using System;

 using System.Collections.Generic;

 using System.Linq;

 using System.Web;

/// <summary>

///Test 的摘要说明

/// </summary>

public class Test:IHttpModule

{

 public Test()

 {

  //

  //TODO: 在此处添加构造函数逻辑

  //

 }

    #region IHttpModule 成员

 public void Dispose()

        {

           //throw new NotImplementedException();

        }

 public void Init(HttpApplication context)

       {

        // 注册HttpApplication应用程序 AcquireRequestState 事件

        context.AcquireRequestState += new EventHandler(context_AcquireRequestState);

        }

 void context_AcquireRequestState(object sender, EventArgs e)

        {

             HttpApplication app =(HttpApplication) sender;

             //获取当前请求的路径

            string path = app.Context.Request.Path;

            //判断是不是登陆页面

             if (!path.EndsWith("login.aspx"))

               {   //判断当前登录用户是不是admin

                  if (app.Context.User.Identity.Name!="admin")

                   {   //如果登录用户不是admin就无权查看当前页面,重定向错误页面

                      app.Context.Server.Transfer("Error.aspx?message=" + path + "");

                   }

         }

         //throw new NotImplementedException();

    }

    #endregion

}

 http://xiaolongwang168.blog.163.com/blog/static/123642111201173095828628/