简体   繁体   English

没有调用HttpModule Init方法

[英]HttpModule Init method were not called

Recently I was implementing a HttpMoudle. 最近我正在实施一个HttpMoudle。 and stuck with the error which is said System.NullReferenceException: Object reference not set to an instance of an object. 并且System.NullReferenceException: Object reference not set to an instance of an object.了错误,即System.NullReferenceException: Object reference not set to an instance of an object.

Here is my code . 这是我的代码。

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
    }

Especially when multiple user get into the Website. 特别是当多个用户进入网站时。 the exception of NullReferenceException happened. 发生NullReferenceException的例外。 and when I debug, I found sometimes Init method may not be called. 当我调试时,我发现有时可能不会调用Init方法。 Maybe that is the why the exception happened . 也许这就是异常发生的原因。 Anybody could help me to check it ?Thanks 有人可以帮我检查一下吗?谢谢

you have set as static your main object authProvider , so you need to make synchronize when you make it and delete it. 您已将主对象authProvider设置为静态,因此您需要在进行同步时将其删除并删除它。

private static IAuthProvider authProvider=null;

So you need to write it as: 所以你需要把它写成:

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
    }

The problem is (as Aristos pointed out) that you have made the authProvider static. 问题是(正如Aristos指出的那样)你已经使authProvider静态的。

That means that when several users are generating requests at the same time, there will be several instances of you HttpModule running simultaneously. 这意味着当几个用户同时生成请求时,会有几个HttpModule同时运行的实例。 But they will all share one authProvider . 但他们都将共享一个 authProvider

So it's possible that User A starts a request, causing a new instance of you module to run it's Init method. 因此, 用户A可能会启动请求,导致您的模块的新实例运行它的Init方法。 Then the thread handling that request is put on hold and another request from User B starts, causing another a new intance of the module to run it's Init method. 然后处理该请求的线程被置于保持状态,并且来自用户B的另一个请求启动,导致另一个模块的新intance运行它的Init方法。 This will overwrite the instance in authProvider that was put there in User A 's request . 这将覆盖在用户A的请求中放置的authProvider中的实例。 Then that thread is put on hold and the previous thread from User A is resumed and finishes processing the request, thereby Disposing the authProvider (set by User B 's request) and setting it to null. 然后线程被置于保持状态,并恢复用户A的前一个线程并完成处理请求,从而处理authProvider (由用户B的请求设置)并将其设置为null。 After that the request from User B once again resumes and finds that authProvider is now null. 之后,用户B的请求再次恢复,并发现authProvider现在为空。

Based on the code you have provided, it seems like the simplest possible solution is to simply remove the static keyword from the line: 根据您提供的代码,似乎最简单的解决方案是简单地从行中删除static关键字:

private static IAuthProvider authProvider=null;

Then each instance of the HttpModule will have it's own copy of the authProvider and one request will not affect the state of another. 然后, HttpModule每个实例都拥有它自己的authProvider副本,一个请求不会影响另一个请求的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM