HttpModule 示例

转载 2007年09月12日 20:39:00
—— 一点一点学ASP.NET
文野:2006年8月11日星期五
 
概述
从前面的章节我们知道HTTP Handler提供了类似于ISAPI Server Extention的功能,而HttpModule实现了类似于ISAPI Filter的功能。使用自定义的Handler会覆盖系统默认的Handler,而Module是可以多个同时存在的。
HttpHandler与HttpModule简单来说其实都是对一个请求上下文的处理,但它们两个所处的功能角色是完全不一样的。我暂时还想不出一个既简单又能体现HttpHandler优点的场景来,其实Page类就是一个实现了IHttpHandler的类,在Ajax中也有相关的实现,以及Asp.Net Forums V2中有两个比较简单的实现(AvatarHttpHandler和VCardHttpHandler),大家可以去参考一下。
下面是一个检查用户是否登录及模块授权的HttpModule示例。
 
场景
一个网站,有一个首页(Default.aspx),一个登录页面(Login.aspx),两个模块(模块1和模块2)。
一、               当用户在未登录的情况下访问网站的任一个页面都会跳转到登录页面要求用户登录,登录完成后跳转到网站首页并在每个页面上显示欢迎词。
二、               假设有两个用户,一个“文野”,一个“stwyhm”,文野可以访问模块1,stwyhm可以访问模块2,当他们访问各自有权访问的模块时,显示模块给出的欢迎词,如果访问的模块没有访问权限,给出错误提示。其它用户只能访问指定模块以后的页面。
 
示例
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
 
namespace AuthorizationModule
{
    ///<summary>
    ///说明:检查用户登录的Module
    ///作者:文野
    ///联系:stwyhm.cnblogs.com
    ///</summary>
    public class UserAuthorizationModule : IHttpModule
    {
        #region IHttpModule 成员
 
        public void Dispose()
        { }
 
        public void Init(HttpApplication context)
        {
            context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
        }
 
        void context_AcquireRequestState(object sender, EventArgs e)
        {
            // 获取应用程序
            HttpApplication application = (HttpApplication)sender;
 
            // 检查用户是否已经登录
            if (application.Context.Session["UserName"] == null || application.Context.Session["UserName"].ToString().Trim() == "")
            {
                // 获取Url
                string requestUrl = application.Request.Url.ToString();
                string requestPage = requestUrl.Substring(requestUrl.LastIndexOf('/') + 1);
 
                // 如果请求的页面不是登录页面,刚重定向到登录页面。
                if (requestPage != "Login.aspx")
                    application.Server.Transfer("Login.aspx");
            }
            else
            {
                // 已经登录,向每个请求的页面打印欢迎词。
                application.Response.Write(string.Format("欢迎您!{0}!", application.Context.Session["UserName"]));
            }
        }
 
        #endregion
    }
 
    ///<summary>
    ///说明:检查用户是否有权使用模块的Module
    ///作者:文野
    ///联系:stwyhm.cnblogs.com
    ///</summary>
    public class SystemModuleAuthorizationModule : IHttpModule
    {
 
       #region IHttpModule 成员
 
        public void Dispose()
        {
        }
 
        public void Init(HttpApplication context)
        {
            context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
        }
 
        void context_AcquireRequestState(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
 
            // 如果用户未登录,则无需检查模块授权,因为请求会被用户登录Module重定向到登录页面。
            if (application.Session["UserName"] == null)
                return;
 
            // 获取用户名和Url
            string userName = application.Session["UserName"].ToString();
            string url = application.Request.Url.ToString();
 
            // 如果用户没有被授权,请求被终止,并打印提示信息。
            if (!Validator.CanUseModule(userName, url))
            {
                application.CompleteRequest();
                application.Response.Write(string.Format("对不起!{0},您无权访问此模块!", userName));
            }
        }
 
        #endregion
    }
 
    public class Validator
    {
       ///<summary>
        ///检查用户是否被授权使用模块。
        ///文野可以使用模块,stwyhm可以使用模块,所有用户都可以请求限定模块以外的页面
        ///</summary>
        ///<param name="userName"></param>
        ///<param name="url"></param>
        ///<returns></returns>
        public static bool CanUseModule(string userName, string url)
        {
            if (!url.Contains("模块"))
                return true;
            else if (userName == "文野" && url.Contains("模块1"))
                return true;
            else if (userName == "stwyhm" && url.Contains("模块2"))
                return true;
            else
                return false;
        }
    }
}
页面中除了简单的登录保存用户名到Session的代码及一些Html呈现代码外无任何代码。
 
执行结果
第一步:打开网站首页,因示登录被跳转到登录页面

 
第二步:登录成功后跳转到首面。

 
第三步:访问有权进入的模块1

 
第四步:访问无权进入的模块2

 
开发注意点
    无论是通过Url发出请求,还是一个按钮引起的页面回发,对IIS来说是一样的,都是一次请求。而HttpModule中的事件一般都在页面事件前,特别是控件事件,所以如果在HttpModule的事件中对请求进行过滤处理后就不会执行到页面事件或控件事件,这就是上面示例的UserAuthorizationModule代码中为什么要对请求页面是否是Login.aspx进行判断的原因了。
 
总结
这里两个自定义的HttpModule实现了它们各自所要达到的过滤请求的功能,一个限制用户登录,一个限制模块访问,当然实际应用中比这要复杂许多。这样的验证方式是简单的、安全的,代码在修改时只要修改相应的HttpModule就可以了,无需在每个页面都写相同的验证代码,也不会发生在Url地址栏里输入一段Url就可以跳过登录及其它验证的情况了。在这两个HttpModule中,因为都要涉及到对Session的访问,所有都使用了AcquireRequestState事件,大家可以根据实际情况使用不同的事件,可以参考我前面文章中的那副HttpModule生命周期图。
 
相关文章
一点一点学ASP.NET之基础概念——HTTP运行期与页面执行模型
    一点一点学ASP.NET之基础概念——HttpModule
    一点一点学ASP.NET之基础概念——HttpHandler
 
本文源码
    下载
posted on 2006-08-11 09:59 文野 阅读(2938) 评论(12)  编辑  收藏 所属分类: 一点一点学ASP.NET

Feedback

# re: 一点一点学ASP.NET之示例——HttpModule 示例 2006-08-11 11:16 文野
@aspnetx
不好意思,贴上去时不知怎么的,1和2丢了。
已修改。  回复  更多评论
  

# re: 一点一点学ASP.NET之示例——HttpModule 示例 2006-08-11 12:34 aspnetx
@文野
呵呵,我说的呢  回复  更多评论
  

# re: 一点一点学ASP.NET之示例——HttpModule 示例 2006-11-05 09:58 杰仔[匿名]
请问:

我用一个页面index.aspx,做一个连接到style.aspx

index.aspx连接代码:

<a href='style.aspx?xk=all&gd=all&lanmu=<%#Eval("lanmu") %>&lid=<%#Eval("lid") %>'><%#Eval("lanmu")%></a>

style.aspx获取lanmu值,查询数据库resource

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Data.SqlClient;

public partial class style : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
this.DLRe.DataSource = DLCON();
this.DLRe.DataBind();
}
}
private PagedDataSource DLCON()
{
string lanmu = Request.QueryString["lanmu"].ToString();
SqlConnection con = db.createConnection();
con.Open();
SqlDataAdapter sdr = new SqlDataAdapter();
sdr.SelectCommand = new SqlCommand("select * from resource where lanmu = '" + lanmu + "'", con);
DataSet ds = new DataSet();
sdr.Fill(ds, "resource");
PagedDataSource pds = new PagedDataSource();
pds.DataSource = ds.Tables["resource"].DefaultView;
pds.AllowPaging = true;
pds.PageSize = 30;
pds.CurrentPageIndex = Convert.ToInt32(Request.QueryString["page"]);
return pds;
}

protected void DLRe_ItemDataBound(object sender, DataListItemEventArgs e)
{
string strPathAndQuery = Request.RawUrl;
Response.Write(strPathAndQuery);
//string filename=strPathAndQuery.Substring (strPathAndQuery.LastIndexOf ("/"));
if (e.Item.ItemType == ListItemType.Footer)
{
int n = DLCON().PageCount;
int i = DLCON().CurrentPageIndex;
//总页数
Label lblpc = (Label)e.Item.FindControl("lblpc");
lblpc.Text = n.ToString();

//当前页数
Label lblp = (Label)e.Item.FindControl("lblp");
lblp.Text = Convert.ToString(i + 1);

//首页
HyperLink hlfir = (HyperLink)e.Item.FindControl("hlfir");
hlfir.NavigateUrl = "?page=0";

//尾页
HyperLink hlla = (HyperLink)e.Item.FindControl("hlla");
hlla.NavigateUrl = "?page=" + Convert.ToInt32(n - 1);

//上一页
HyperLink hlp = (HyperLink)e.Item.FindControl("hlp");
hlp.NavigateUrl = "?page=" + Convert.ToInt32(i);

//下一页
HyperLink hln = (HyperLink)e.Item.FindControl("hln");
hln.NavigateUrl = "?page=" + Convert.ToInt32(i + 1);

//当为第一页
if (i <= 0)
{
hlfir.Enabled = false;
hlp.Enabled = false;
hln.Enabled = true;
hlla.Enabled = true;
}

//当为最后一页
if (i > n - 2)
{
hlfir.Enabled = true;
hlp.Enabled = true;
hln.Enabled = false;
hlla.Enabled = false;
}
}
}


分页连接不知道怎样写才好,想了很久,请问大家有什么方法可以解决这个问题,谢谢了...这是我学到asp.net一直没解决的问题,
# re: 一点一点学ASP.NET之示例——HttpModule 示例 2006-08-11 10:42 aspnetx
 

相关文章推荐

HttpModule重写机制

  • 2011年07月25日 00:43
  • 55KB
  • 下载

HttpModule,HttpHandler详细解释

  • 2008年12月16日 11:25
  • 148KB
  • 下载

HttpHandler与HttpModule的用处与区别

出处:http://www.cnblogs.com/JimmyZhang/archive/2007/09/15/894124.html      问题1:什么是HttpHandler?  ...
  • for_cxc
  • for_cxc
  • 2016年07月16日 13:38
  • 1979

c#基于HttpModule的用户身份验证

  • 2010年10月25日 23:53
  • 7KB
  • 下载

HttpModule实例

  • 2013年08月15日 23:40
  • 5KB
  • 下载

HttpModule的认识

HttpModule是向实现类提供模块初始化和处置事件。当一个HTTP请求到达HttpModule时,整个ASP.NET Framework系统还并没有对这个HTTP请求做任何处理,也就是说此时对于H...
  • wzwlln
  • wzwlln
  • 2011年03月02日 15:19
  • 358

httpmodule和httphandler

  • 2012年12月13日 16:50
  • 1.98MB
  • 下载

HttpModule实现同时一人在线.rar

  • 2009年05月16日 00:28
  • 13KB
  • 下载

HttpHandler与HttpModule

ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后,仍经过Pi...
  • okhui
  • okhui
  • 2011年04月29日 10:31
  • 213

HttpModule检验Session值

  • 2014年01月14日 17:38
  • 16KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HttpModule 示例
举报原因:
原因补充:

(最多只允许输入30个字)