【问题标题】:Server cannot modify cookies after HTTP headers have been sent, how Fix?发送 HTTP 标头后服务器无法修改 cookie,如何修复?
【发布时间】:2012-01-07 09:49:56
【问题描述】:

如果 cookie 中存在用户名和密码,我想在 masterpage 的 page_load 自动登录我的用户!
所以我写了下面的代码:

        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);

这个错误是什么意思,我该如何防止它?

【问题讨论】:

  • Session.Clear() 或 Session.Abandon() ?

标签: c# asp.net cookies forms-authentication


【解决方案1】:

如果您使用 ASP.Net 标准表单身份验证,如果您使用持久性 cookie,则此功能可用于表单身份验证。请参阅 MSDN 文章 here。检查文档的“创建表单身份验证 Cookie”部分。

您不需要保留用户名\密码组合是 cookie。这不是一个好习惯,因为任何人都可以从 cookie 中嗅出这个用户名\密码。我强烈建议您阅读上述文章以了解表单身份验证的工作原理。

【讨论】:

  • 原因可能是用户已通过身份验证,并且其表单身份验证 cookie 已设置。尝试将用户 ID 放入新的 cookie 中
【解决方案2】:

“System.Web.HttpException:发送 HTTP 标头后服务器无法修改 cookie。”

该错误表明您在 http 响应完成后尝试修改 cookie。

我认为问题是您在执行后尝试修改 cookie FormsAuthentication.SignOut()。

根据 MSDN,调用 SignOut() 方法时会发生这种情况

调用 SignOut 方法时,通过调用 Redirect 方法并将 endResponse 参数设置为 false,重定向到应用程序的登录页面。在当前页面完成执行之前不会发生重定向,因此可以运行其他代码。如果代码不包含显式重定向到另一个页面,用户将被重定向到应用程序配置文件中配置的登录页面。

因此,您正在尝试在重定向发生后修改 cookie。您可以通过在重定向前设置 cookie 值来避免此错误。

【讨论】:

  • 感谢您的回答/但正如您所见,我的方法中没有 SignOut 或 Redirection (LoadDataFromCookieIfExistAndLogin())。所以为什么仍然有这个错误 -> 只有 elmah 向我显示了这个错误,Visual Studio 显示了这个调试期间出错。在浏览器中处理页面时不会出现此错误!
  • 我的意思是 FormsAuthentication.SignOut();请确保 FormsAuthentication.SignOut();在您修改/设置 cookie 值之前不会执行
  • -> 没有 FormsAuthentication.SignOut();在修改/设置cookie值之前,这正是我想知道为什么我有异常?
  • 哪个顺序合适? 1) FormsAuthentication.SignOut() 2) Session.Abandon() 3) var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, ""); cookie.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie);
【解决方案3】:

为了快速测试,我已经清除了浏览器历史记录,并且在我的终端上运行良好..

【讨论】:

  • 这实际上不会修复该异常,除非您正在做一些非常奇怪的事情,在这种情况下它会回来。
猜你喜欢
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2015-12-05
  • 1970-01-01
  • 2011-09-13
相关资源
最近更新 更多