惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
M
MIT News - Artificial intelligence
MyScale Blog
MyScale Blog
博客园_首页
G
Google Developers Blog
博客园 - 【当耐特】
美团技术团队
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Vercel News
Vercel News
小众软件
小众软件
博客园 - 司徒正美
雷峰网
雷峰网
T
Tailwind CSS Blog
V
V2EX
博客园 - 三生石上(FineUI控件)
F
Fortinet All Blogs
罗磊的独立博客
量子位
P
Proofpoint News Feed
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
A
About on SuperTechFans
Hugging Face - Blog
Hugging Face - Blog

博客园 - Koven

如何拓展你的人脉关系 所谓职业(转载) 期待已久的一本电子书出来了:Applying Domain-Driven Design and Patterns: With Examples in C# and .NET 搜索引擎相关站点收集(转载) 中文搜索引擎系统架构(转载) 中文搜索引擎网络蜘蛛(转载) 中文搜索引擎中的排序技术(转载) 中文分词介绍(转载) 转载一篇不错的关于.NET中内存使用的文章 Data Type Performance Tuning Tips for Microsoft SQL Server(转载) 怎么在ASP.NET 2.0中使用Membership (转载) ASP.NET服务器控件与组件基础概念——HttpHandler (转载) ASP.NET服务器控件与组件基础概念——HttpModule(转载) Tips to improve the performance of ASP.Net Application Best practices for .Net Performance - I HTTP运行期与页面执行模型(转载) XML格式的网站配置文件常见读写方案比较(转载) ASP.NET应用中十大常见的潜在问题(转载) 微软研发75条心得(转载)
HttpModule 示例(转载)
Koven · 2006-08-11 · via 博客园 - Koven

概述

从前面的章节我们知道HTTP Handler提供了类似于ISAPI Server Extention的功能,而HttpModule实现了类似于ISAPI Filter的功能。使用自定义的Handler会覆盖系统默认的Handler,而Module是可以多个同时存在的。

HttpHandlerHttpModule简单来说其实都是对一个请求上下文的处理,但它们两个所处的功能角色是完全不一样的。我暂时还想不出一个既简单又能体现HttpHandler优点的场景来,其实Page类就是一个实现了IHttpHandler的类,在Ajax中也有相关的实现,以及Asp.Net Forums V2中有两个比较简单的实现(AvatarHttpHandlerVCardHttpHandler),大家可以去参考一下。

下面是一个检查用户是否登录及模块授权的HttpModule示例。

场景

一个网站,有一个首页(Default.aspx),一个登录页面(Login.aspx),两个模块(模块1和模块2)。

一、               当用户在未登录的情况下访问网站的任一个页面都会跳转到登录页面要求用户登录,登录完成后跳转到网站首页并在每个页面上显示欢迎词。

二、               假设有两个用户,一个“文野”,一个“stwyhm”,文野可以访问模块1stwyhm可以访问模块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

本文源码

    下载