【问题标题】:HttpModule Init method were not called未调用 HttpModule Init 方法
【发布时间】:2012-08-22 08:51:22
【问题描述】:

最近我正在实现一个 HttpMoudle。并坚持说System.NullReferenceException: Object reference not set to an instance of an object.

这是我的代码。

public class MyHttpModuler : IHttpModule
    {
        private static IAuthProvider authProvider=null;
        #region IHttpModule members
        /// <summary>
        /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
        /// </summary>
        public void Dispose()
        {
            authProvider.Dispose();
            authProvider = null;
        }

        public void Init(HttpApplication application)
        {
            authProvider = new BasicAuthProvider("achievo");
            application.BeginRequest += new EventHandler(Application_BeginRequest);

        }

        private void Application_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;
            HttpRequest request = app.Request;
            HttpResponse response = app.Response;
            TryAuthenticate(app);                    
        }
        #endregion


        #region private method
        /// <summary>
        /// Tries to authenticate the user
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        private bool TryAuthenticate(HttpApplication context)
        {
            string authHeader = context.Request.Headers["Authorization"];
            if (!string.IsNullOrEmpty(authHeader))
            {
                if (authHeader.StartsWith("basic ", StringComparison.InvariantCultureIgnoreCase))
                {

                    string userNameAndPassword = Encoding.Default.GetString(
                        Convert.FromBase64String(authHeader.Substring(6)));
                    string[] parts = userNameAndPassword.Split(':');
                     if (authProvider.IsValidUser(parts[0], parts[1]))
                    {
                        //the authProvider object sometimes is null .Why?                            
                        return true;
                    }
                }
            }
            return false;
        }
        #endregion
    }

public class BasicAuthProvider : IAuthProvider
    {

        #region IAuthProvider Members

        public string DomainName { get; set; }

        public BasicAuthProvider(string sDmName)
        {
            DomainName = sDmName;
        }

        public bool IsValidUser(string userName, string password)
        {

            string sFullName = "LDAP://" + DomainName + ".com";
            bool bLogin = ADHelper.IsAuthenticated(sFullName, DomainName + @"\" + userName, password);
            return bLogin;
        }


        public bool IsRequestAllowed(HttpRequest request,string sName)
        {
            return sName == "joe.wang";
        }



        public void Dispose()
        {

        }

        #endregion
    }

尤其是当多个用户进入网站时。发生 NullReferenceException 异常。当我调试时,我发现有时Init 方法可能不会被调用。也许这就是发生异常的原因。任何人都可以帮我检查一下吗?谢谢

【问题讨论】:

    标签: asp.net httpmodule


    【解决方案1】:

    问题是(正如 Aristos 指出的那样)您已将 authProvider 设为静态。

    这意味着当多个用户同时产生请求时,会有多个你HttpModule的实例同时运行。但他们都会分享一个 authProvider

    因此,用户 A 可能会启动一个请求,从而导致您的模块的一个新实例运行它的 Init 方法。然后处理该请求的线程被搁置,来自 User B 的另一个请求开始,导致另一个新的模块实例运行它的 Init 方法。这将覆盖 authProvider 中放置在 User A 的 request 中的实例。然后那个线程被搁置,用户A的前一个线程被恢复并完成处理请求,从而释放authProvider(由用户B设置 的请求)并将其设置为 null。之后用户 B 的请求再次恢复,发现 authProvider 现在为空。

    根据您提供的代码,似乎最简单的解决方案是简单地从该行中删除 static 关键字:

    private static IAuthProvider authProvider=null;
    

    然后HttpModule 的每个实例都将拥有自己的authProvider 副本,并且一个请求不会影响另一个请求的状态。

    【讨论】:

    • 最好让 authProvider 单例?
    【解决方案2】:

    您已将主对象authProvider 设置为静态,因此您需要在创建和删除时同步。

    private static IAuthProvider authProvider=null;
    

    所以你需要写成:

    public class MyHttpModuler : IHttpModule
        {
            //can not be shared with others request.
            //private IAuthProvider authProvider = null;
    
            //We do not need it now.
            //private static readonly object _lockObj = new object();
    
            #region IHttpModule members
            /// <summary>
            /// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
            /// </summary>
            public void Dispose()
            {
                //authProvider.Dispose();
            //authProvider = null;
            }
    
            public void Init(HttpApplication application)
            { 
    
                application.BeginRequest += new EventHandler(Application_BeginRequest);       
            }
    
            private void Application_BeginRequest(object sender, EventArgs e)
            {
                HttpApplication app = (HttpApplication)sender;
                HttpRequest request = app.Request;
                HttpResponse response = app.Response;
                TryAuthenticate(app);                    
            }
            #endregion
    
    
            #region private method
            /// <summary>
            /// Tries to authenticate the user
            /// </summary>
            /// <param name="context">The context.</param>
            /// <returns></returns>
            private bool TryAuthenticate(HttpApplication context)
            {
                IAuthProvider authProvider = new BasicAuthProvider("achievo");  
                string authHeader = context.Request.Headers["Authorization"];
                if (!string.IsNullOrEmpty(authHeader))
                {
                    if (authHeader.StartsWith("basic ", StringComparison.InvariantCultureIgnoreCase))
                    {
    
                        string userNameAndPassword = Encoding.Default.GetString(
                            Convert.FromBase64String(authHeader.Substring(6)));
                        string[] parts = userNameAndPassword.Split(':');
                         if (authProvider.IsValidUser(parts[0], parts[1]))
                        {
                            //the authProvider object sometimes is null .Why?     
                            authProvider=null;                        
                            return true;
                        }
                    }
                }
                authProvider=null;  
                return false;
            }
            #endregion
        }
    

    【讨论】:

    • 嗨,您的代码似乎还有一些问题。请阅读 user1429080 的答案。一个线程处理 httpmodule 并将 authProvider 设置为 null 。因为它是静态的。在那一刻,另一个线程刚刚发现它是 null 。所以你的代码仍然有缺陷。看到了吗?
    • @malai.kuangren 你能在确保代码正常工作时更正代码吗?
    • @malai.kuangren 在我之前还有其他人拒绝您的编辑,对此我很抱歉,并且无法将其取回,所以我从您的编辑中手动执行此操作。
    猜你喜欢
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多