3

最近、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
    }

特に複数のユーザーが Web サイトにアクセスする場合。NullReferenceException の例外が発生しました。Initデバッグすると、メソッドが呼び出されない場合があることがわかりました。たぶんそれが例外が発生した理由です。誰でも私がそれをチェックするのを手伝ってくれますか?ありがとう

4

2 に答える 2

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
    }
于 2012-08-22T09:25:51.673 に答える
2

問題は ( Aristosが指摘したように)authProvider静的にしたことです。

つまり、複数のユーザーが同時にリクエストを生成している場合、複数のインスタンスがHttpModule同時に実行されます。しかし、それらはすべて1 つ authProviderを共有します。

したがって、ユーザー Aがリクエストを開始し、モジュールの新しいインスタンスがそのメソッドを実行する可能性がありますInit。次に、そのリクエストを処理するスレッドが保留になり、ユーザー Bからの別のリクエストが開始され、別のモジュールの新しいインスタンスがそのInitメソッドを実行します。これにより、ユーザー Aのリクエストでそこに置かれた authProvider のインスタンスが上書きされます。次に、そのスレッドが保留され、ユーザー Aからの前のスレッドが再開され、要求の処理が終了します。これにより、authProvider(ユーザー Bの要求によって設定された) が破棄され、null に設定されます。その後、ユーザー B からの要求が再び再開され、authProvider現在は null であることがわかります。

あなたが提供したコードに基づいて、最も簡単な解決策はstatic、行からキーワードを削除することです。

private static IAuthProvider authProvider=null;

の各インスタンスにはHttpModule独自の のコピーがありauthProvider、1 つの要求が別の状態に影響することはありません。

于 2012-08-22T10:12:25.940 に答える