1. ホーム
  2. c#

[解決済み] HTTPヘッダが送信された後、サーバーはクッキーを変更できません。

2022-02-25 04:26:28

質問

マスターページのページロード時に、ユーザー名とパスワードがクッキーに存在する場合、ユーザーに自動ログインさせたいのですが!
ということで、以下のようなコードを書きました。

        protected void Page_Load(object sender, EventArgs e)
        {
            LoadDataFromCookieIfExistAndLogin();
        }

private void LoadDataFromCookieIfExistAndLogin()
{
    string Query = Request.Url.Query.ToString();
    string[] Ar_Query = new string[2];
    string[] splitter = { "%2f" };
    Ar_Query = Query.Split(splitter, System.StringSplitOptions.None);
    string[] Ar_new_Query = new string[2];
    int minLength = Math.Min(Ar_Query.Length, Ar_new_Query.Length);
    Array.Copy(Ar_Query, Ar_new_Query, minLength);
    if (string.IsNullOrEmpty(Ar_new_Query[1]))
    {
        Ar_new_Query[1] = string.Empty;
    }

    if ((Request.QueryString["ReturnURL"] != null) && (Ar_new_Query[1].ToString().ToUpper() == "ADMIN"))
    {
        Session.Clear();
        FormsAuthentication.SignOut();
    }
    else if ((Request.QueryString["ReturnURL"] != null) && (Ar_new_Query[1].ToString().ToUpper() == "ELMAH.AXD"))
    {
        Session.Clear();
        FormsAuthentication.SignOut();
    }
    else
    {
        HttpCookie Situation_Cookie = Request.Cookies["Situation"];
        if (Situation_Cookie != null)
        {
            if (Situation_Cookie["Login"] == "Yes")
            {
                HttpCookie Data_Cookie = Request.Cookies["Data"];
                if (Data_Cookie != null)
                {
                    string UserName = Data_Cookie["UserName"].ToString();
                    string PassWord = ata_Cookie["PassWord"].ToString();

                    string HashedPass = FormsAuthentication.HashPasswordForStoringInConfigFile(PassWord, "MD5");
                    DataSet dsUsers = DataLayer.Users.SelectRowForLogin_FromCookie(UserName, HashedPass);
                    if (dsUsers.Tables["Users"].Rows.Count > 0)
                    {
                        DataRow drUsers = dsUsers.Tables["Users"].Rows[0];

                        if (Session["User_ID"] == null)
                        {
                            Session["UserName"] = UserName;
                            Session["Password"] = PassWord;
                            Session["User_ID"] = drUsers["ID"].ToString();
                            Session["UserType_ID"] = drUsers["UserType_ID"].ToString();
                            DataLayer.OnlineUsers.UpdateRow_UserID_By_SessionID(
                                                                                 Session["User_ID"],
                                                                                 Session.SessionID);
                        }
                        if (!HttpContext.Current.User.Identity.IsAuthenticated)
                        {
                            FormsAuthentication.SetAuthCookie(drUsers["ID"].ToString(), true);
                        }
                    }
                }
            }
        }
    }
}

また、私のログインコードを理解するために、私は以下のようなRoleProviderを使用しています。

  using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Security;
    using System.Data;

    namespace NiceFileExplorer.Classes
    {
        public class NiceFileExplorerRoleProvider : RoleProvider
        {
            public override void AddUsersToRoles(string[] usernames, string[] roleNames)
            {
                throw new NotImplementedException();
            }

            public override string ApplicationName
            {
                get
                {
                    throw new NotImplementedException();
                }
                set
                {
                    throw new NotImplementedException();
                }
            }

            public override void CreateRole(string roleName)
            {
                throw new NotImplementedException();
            }

            public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
            {
                throw new NotImplementedException();
            }

            public override string[] FindUsersInRole(string roleName, string usernameToMatch)
            {
                throw new NotImplementedException();
            }

            public override string[] GetAllRoles()
            {
                throw new NotImplementedException();
            }

            //public override string[] GetRolesForUser(string username)
            public override string[] GetRolesForUser(string User_ID)
            {
                string[] UserTypes = new string[1];
                DataSet dsUser = DataLayer.Users.SelectRowWithUserTypeInfo(int.Parse(User_ID));
                if (dsUser.Tables["Users"].Rows.Count > 0)
                {
                    DataRow drUser = dsUser.Tables["Users"].Rows[0];
                    UserTypes[0] = drUser["Name"].ToString();
                }
                if (User_ID == "-255")
                {
                    UserTypes[0] = "Administrators";
                }
                return UserTypes;
            }

            public override string[] GetUsersInRole(string roleName)
            {
                throw new NotImplementedException();
            }

            public override bool IsUserInRole(string username, string roleName)
            {
                throw new NotImplementedException();
            }

            public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
            {
                throw new NotImplementedException();
            }

            public override bool RoleExists(string roleName)
            {
                throw new NotImplementedException();
            }
        }

}

時々、以下のようなエラーが発生します。

System.Web.HttpException: HTTPヘッダが送信された後、サーバーはCookieを変更できません。

System.Web.HttpUnhandledException (0x80004005): Exception of type 'System.Web.HttpUnhandledException' was thrown. ---> System.Web.HttpException (0x80004005): Server cannot modify cookies after HTTP headers have been sent.
   at System.Web.HttpCookieCollection.Add(HttpCookie cookie)
   at System.Web.Security.FormsAuthentication.SetAuthCookie(String userName, Boolean createPersistentCookie, String strCookiePath)
   at NiceFileExplorer.en.Site1.Page_Load(Object sender, EventArgs e)
   at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

以下の行に問題があるようです。

FormsAuthentication.SetAuthCookie(drUsers["ID"].ToString(), true)を実行します。

このエラーは何を意味し、どうすれば防げるのでしょうか?

解決方法は?

"System.Web.HttpException。HTTPヘッダが送信された後、サーバーはCookieを変更できません。

<ブロッククオート

このエラーは、http応答が完了した後にクッキーを変更しようとしていることを示しています。

を実行した後に、Cookieを変更しようとしているのが問題だと思います。 FormsAuthentication.SignOut()です。

MSDNによると、SignOut()メソッドが呼ばれると、このようなことが起こります。

SignOutメソッドが呼び出されると、endResponseパラメータにfalseを指定してRedirectメソッドを呼び出し、アプリケーションのログインページにリダイレクトされます。リダイレクトは、現在のページの実行が終了するまで行われないため、追加のコードを実行することができます。コードに他のページへの明示的なリダイレクトが含まれていない場合、ユーザーはアプリケーションの設定ファイルで設定されたログインページにリダイレクトされます。

つまり、リダイレクトが起こった後にクッキーを変更しようとしているのですね。リダイレクトが起こる前にクッキーの値を設定することで、このエラーを回避することができます。