FormsAuthentication.SignOut()不会注销用户
FormsAuthentication.SignOut() does not log the user out的问题出现的原因是,该方法只是清除了身份验证的cookie,并没有清除会话的cookie。为了解决这个问题,需要手动清除会话的cookie,并且还需要在客户端上使缓存失效。
解决方法如下:
1. 首先,需要在退出登录的方法中清除身份验证cookie和会话cookie,并将空cookie添加到响应中。
public ActionResult LogOff() { FormsAuthentication.SignOut(); Session.Clear(); Session.Abandon(); // 清除身份验证cookie HttpCookie rFormsCookie = new HttpCookie(FormsAuthentication.FormsCookieName, ""); rFormsCookie.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(rFormsCookie); // 清除会话cookie HttpCookie rSessionCookie = new HttpCookie("ASP.NET_SessionId", ""); rSessionCookie.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(rSessionCookie); }
2. 其次,需要在响应中使缓存失效,以防止在退出登录后缓存页面。
// 在客户端上使缓存失效 Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); // 重定向到首页(应该被拦截并重定向到登录页) return RedirectToAction("Index", "Home");
通过以上两个步骤,可以解决FormsAuthentication.SignOut()方法无法完全退出用户的问题。这个问题在ASP.NET 4.51和MVC 5.1开发环境中出现。
问题出现的原因是调用FormsAuthentication.SignOut()方法后,用户仍然可以浏览网站,因为在每个新的请求中,cookie并没有被清除,用户仍然被认证。在微软的文档中说cookie会被清除,但实际上并没有清除,是否是一个bug?
解决方法是改变代码为以下内容:
FormsAuthentication.SignOut(); Session.Abandon(); // 清除身份验证cookie HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, ""); cookie1.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie1); // 清除会话cookie(对于当前的问题来说不是必需的,但我仍然建议你这样做) SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState"); HttpCookie cookie2 = new HttpCookie(sessionStateSection.CookieName, ""); cookie2.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie2); FormsAuthentication.RedirectToLoginPage();
HttpCookie位于System.Web命名空间。[MSDN参考链接](https://msdn.microsoft.com/en-us/library/system.web.httpcookie(v=vs.110).aspx)。
此解决方法对我有效。但值得注意的是,如果在登录时为FormsAuthentication cookie设置了Domain属性,那么在注销时也需要设置该属性。
不要忘记设置cookie1.Path = FormsAuthentication.FormsCookiePath;
还要设置cookie1.HttpOnly = true;
这似乎是更好的解决方法:Response.Cookies[FormsAuthentication.FormsCookieName].Expires = DateTime.Now.AddDays(-1);
请注意,如果在.ASPXAUTH上设置了Path属性,FormsAuthentication.FormsCookiePath将无法获取它。所以你需要在某个地方设置一个保存的变量,并将其用作cookie1.Path的值。
通过使用一个新的空cookie来覆盖现有的FormsAuthentication cookie,可以确保即使客户端把系统时钟调回,他们仍然无法从cookie中获取任何用户数据。
根据出现的位置不同,FormsAuthentication.RedirectToLoginPage()可能需要跟随Response.End()。
这是一个很棒的代码片段,对我也有帮助。另外,我使用了MSDN文章来获取会话cookie的名称,以防止使用除ASP.NET_SessionId之外的其他内容。
距离上面的回答写下已经过去了5年。这段代码在visual studio 2013中仍然有效吗?你只需将其复制粘贴到logout_button_Click事件中吗?谢谢。
使用LoginStatus控件来注销用户会清除这些cookie吗?
我简直不敢相信,在我多年的开发经验中,我直到现在才遇到这个问题。将它复制粘贴到我的代码中后,它对我有效。
另一个要记住的是:Context.User = null
这不会立即使cookie失效。
如果你需要这样做,那么你的配置有问题,因为FormsAuthentication.SignOut()会这样做,除非你的身份验证配置不正确。但是,如果你想重置cookie的过期日期,至少要做对。HttpContext.Current.Request.Cookies.AllKeys.ToList().ForEach(s => HttpContext.Current.Request.Cookies[s].Expires = DateTime.Now.AddDays(-1))将迭代所有的cookie并将其过期日期重置,所以在注销时不会留下任何东西。
Response.Cookies.Add方法允许在cookie集合中有重复的cookie。使用Response.Cookies.Set方法来确保cookie集合中的cookie唯一性。(来源于msdn:msdn.microsoft.com/en-us/library/system.web.httpcookiecollection.set.aspx)
能否有人将所有这些评论合并成答案?
Session.Abandon()会中止当前会话,但不会清除会话标识符cookie。按设计,会话标识符可以在下一个请求中被重用以启动新的会话。可以使用regenerateExpiredSessionId配置参数来禁用此行为。
如果在该语句之后发生任何错误,FormsAuthentication.SignOut()将无效。我发现你的解决方案有效,但我更喜欢以下方法:
public ActionResult Logout() { FormsAuthentication.SignOut(); return Redirect("~/"); }
嗨dana,我已经在我的应用程序中实现了Windows身份验证进行登录,但问题是当我从应用程序注销时,它没有正确注销,刷新浏览器后用户仍然登录。我尝试了你上面的解决方案,但没有成功。请帮助我解决这个问题。