实现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中设定虚拟目录的内容设定扩展名对应表。
关于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/