HttpModule的几个典型应用场景

1.HttpModule概述

       HttpModule是ASP.net开发中的瑞士军刀,如果适当地应用HttpModule可以提高系统的可维护性,HttpModule以极小的侵入性来解决系统中的具有通用性的问题。

HttpModule的典型应用场景有:

a. 用户验证

b. 权限控制

c. 用户访问控制,比如基于IP来控制用户对系统的访问

d. 脚本(CSS,JS等)的合并

e. URL Rewriting

f. 本地化(Localization)

g. 异常处理

h. 其他方面。

实际上,.net Framework中就大量采用了HttpModule.比如在.net 4.0的web.config文件中有如下的HttpModule.

 <add name="OutputCache" type="System.Web.Caching.OutputCacheModule" />
 <add name="Session" type="System.Web.SessionState.SessionStateModule" />
 <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule" />
 <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
 <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule" />
 <add name="RoleManager" type="System.Web.Security.RoleManagerModule" />
 <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule" />
 <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule" />
 <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule" />
 <add name="Profile" type="System.Web.Profile.ProfileModule" />
 <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
 <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
 <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" />
 <add name="ScriptModule-4.0" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>

这里仅仅展示用户验证,本地化和防止用户重复提交。

 

2.用户验证

 

     通过判断Session中是否保存了UserName来判断用户是否已经登录系统。

    用户验证的事件必须是在HttpApplication的AcquireRequestState及其以后的事件中处理,因为Session只有在AcquireRequestState及其以后的事件中才是可用的。

app.Context.Handler is IRequiresSessionState || app.Context.Handler is IReadOnlySessionState

对Css,js文件不需要进行验证,比如当Login.aspx引用了js文件的时候,那么即使用户没有登录,那么Login.aspx和js文件都是可以被访问到。

HttpMOdule的代码如下:

 public class LoginHttpModule : IHttpModule
    {
        #region IHttpModule 成员

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.AcquireRequestState += new EventHandler(loginCheck_PostAcquireRequestState);
            
        }

        #endregion

        private void loginCheck_PostAcquireRequestState(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            if (app.Context.Handler is IRequiresSessionState || app.Context.Handler is IReadOnlySessionState)
            {
                if (app.Context.Session["UserName"] == null &&
                    !app.Context.Request.RawUrl.EndsWith("Login.aspx"))
                    app.Context.Response.Redirect("~/Login.aspx");
                
            }
        }
    }

 

 

3.本地化,比如根据不同的国家设置不同的日期格式

 

 /// <summary>
    /// 当然可可以在asp.net的页面中override InitializeCulture.
    /// </summary>
    public class LocalizationHttpModule : IHttpModule
    {
        #region IHttpModule 成员

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(loc_PreRequestHandlerExecute);
            
        }

        
        #endregion

        private void loc_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            //被注释代码仅仅处理Page
            //HttpApplication app = (HttpApplication)sender;
            //if (app.Context.Handler is Page)
            //{
            //    (app.Context.Handler as Page).PreRender += new EventHandler(PreRender);
            //}

            //可以处理Page,实现IHttpHandler,WebService中的国际化问题。
            //法国的日期日期部分的格式 日/月/年
            System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentUICulture;
        }
      
    }

 

当然本地化也可以在asp.net的页面中override InitializeCulture中来处理.但是对于asmx类型的请求在InitializeCulture中是无法处理的。

 

4.防止用户重复提交

 

用户重复提交流程:

 

gif_1[2]

 

 

 

 

解决用户重复提交的流程如下:

gif_2[2]

HttpModule的代码主要是在页面上输出token.

代码如下:

 public class TokenHttpModule : IHttpModule
    {
        #region IHttpModule 成员

        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.PostAcquireRequestState += new EventHandler(token_PostAcquireRequestState);
            
        }

        #endregion

        private void token_PostAcquireRequestState(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            //因为需要访问Session
            if (app.Context.Handler is Page)
            {
                (app.Context.Handler as Page).PreRenderComplete += new EventHandler(PreRenderComplete);
            }
        }

        private void PreRenderComplete(object sender, EventArgs arg)
        { 
            Page page= (sender as Page);
            if (page == null) return;
            if (page.Form == null) return;  
            HttpSessionState session=HttpContext.Current.Session;
            if (session[TokenUtil.TokenKey_InSessions] != null)
            {
                HiddenField ctrl = new HiddenField();
                ctrl.ID = TokenUtil.TokenKey_InPages;
                ctrl.Value = session[TokenUtil.TokenKey_InSessions].ToString();
                ctrl.ClientIDMode = ClientIDMode.Static;
                page.Form.Controls.Add(ctrl);
            }         
        }
    }

 

 

TokenUtil的代码如下:

public static class TokenUtil
    {
        public const string TokenKey_InSessions="tokenkey";
        public const string TokenKey_InPages = "Param_TokenKey";

        public static bool IsValidToken()
        {
            HttpContext context = HttpContext.Current;
            HttpSessionState session = context.Session;
            if (session == null) return false;
            if (session[TokenKey_InSessions] == null) return false;                
            if (String.IsNullOrWhiteSpace(context.Request[TokenKey_InPages]))  return false;
            return session[TokenKey_InSessions].ToString().Equals(context.Request[TokenKey_InPages]);
        }

        public static void SaveToken()
        {
            HttpContext context = HttpContext.Current;
            HttpSessionState session = context.Session;
            if (session == null) return;
            session[TokenKey_InSessions] = Guid.NewGuid().ToString();
        }

        public static void ResetToken()
        {
            HttpContext context = HttpContext.Current;
            HttpSessionState session = context.Session;
            if (session == null) return;
            session.Remove(TokenKey_InSessions);            
        }
    }

 

编辑界面的代码如下:

 

public partial class PersonEdit : BasePage
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!this.IsPostBack)
            {
                base.SaveToken();
            }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            if (!base.IsValidToken())
            {
                //Response.Redirect("InValidToken.aspx");
                Label1.Text = "重复提交!!";
                return;
            }
            int i = 0;
            PersonService ps = new PersonService();
            ps.SavePerson(this.TextBox1.Text);
            base.ResetToken();
            Response.Redirect("PersonList.aspx");
        
        }      
    }

代码文件下载地址.

转载于:https://www.cnblogs.com/ptwlw/archive/2010/06/27/1766139.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值