对此我砸了太久了.如何防止用户在使用FormsAuthentication.SignOut注销后浏览网站的页面?我希望这样做:
FormsAuthentication.SignOut(); Session.Abandon(); FormsAuthentication.RedirectToLoginPage();
但事实并非如此.如果我直接输入URL,我仍然可以浏览到该页面.我有一段时间没有使用自己的安全性,所以我忘记了为什么这不起作用.
用户仍然可以浏览您的网站,因为在您拨打电话时不会清除Cookie,FormsAuthentication.SignOut()
并且每次新请求都会对其进行身份验证.在MS文档中说cookie将被清除,但它们没有,bug?与它完全相同Session.Abandon()
,cookie仍然存在.
您应该将代码更改为:
FormsAuthentication.SignOut(); Session.Abandon(); // clear authentication cookie HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, ""); cookie1.Expires = DateTime.Now.AddYears(-1); Response.Cookies.Add(cookie1); // clear session cookie (not necessary for your current problem but i would recommend you do it anyway) 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参考.
听起来像你没有正确设置你的web.config授权部分.请参阅下面的示例.
使用x64igor和Phil Haselden的上述两个帖子解决了这个问题:
1. x64igor举例说明了注销:
首先需要通过将响应中的空cookie传回注销来清除身份验证Cookie和会话Cookie.
public ActionResult LogOff() { FormsAuthentication.SignOut(); Session.Clear(); // This may not be needed -- but can't hurt Session.Abandon(); // Clear authentication cookie HttpCookie rFormsCookie = new HttpCookie( FormsAuthentication.FormsCookieName, "" ); rFormsCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rFormsCookie ); // Clear session cookie HttpCookie rSessionCookie = new HttpCookie( "ASP.NET_SessionId", "" ); rSessionCookie.Expires = DateTime.Now.AddYears( -1 ); Response.Cookies.Add( rSessionCookie );
2. Phil Haselden上面举例说明了如何在注销后阻止缓存:
您需要通过响应使客户端上的缓存无效.
// Invalidate the Cache on the Client Side Response.Cache.SetCacheability( HttpCacheability.NoCache ); Response.Cache.SetNoStore(); // Redirect to the Home Page (that should be intercepted and redirected to the Login Page first) return RedirectToAction( "Index", "Home" ); }
这里的关键是你说"如果我直接输入一个URL ......".
默认情况下,在表单身份验证下,浏览器会为用户缓存页面.因此,直接从浏览器地址框下拉列表中选择一个URL,或者键入它,可以从浏览器的缓存中获取页面,并且永远不会返回服务器来检查身份验证/授权.解决方案是在每个页面的Page_Load事件或基页的OnLoad()中阻止客户端缓存:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
您可能还想致电:
Response.Cache.SetNoStore();
我之前也在努力解决这个问题.
这是对似乎正在发生的事情的类比......一个新的访问者Joe来到该站点并使用FormsAuthentication通过登录页面登录.ASP.NET为Joe生成一个新标识,并为他提供一个cookie.那个饼干就像是房子的钥匙,只要乔带着那把钥匙回来,他就可以打开锁.每个访问者都会获得一个新密钥和一个新锁.
当FormsAuthentication.SignOut()
被调用时,系统会告诉乔失去的关键.通常,这是有效的,因为乔不再拥有钥匙,他无法进入.
但是,如果Joe回来了,并且确实丢失了钥匙,那么他就会回来!
据我所知,没有办法告诉ASP.NET改变门上的锁!
我可以采用的方法是在Session变量中记住Joe的名字.当他退出时,我放弃了会议,所以我不再有他的名字了.稍后,为了检查他是否被允许,我只是将他的Identity.Name与当前会话的内容进行比较,如果它们不匹配,则他不是有效的访问者.
简而言之,对于一个网站,不要依赖于User.Identity.IsAuthenticated
不检查你的Session变量!
这适合我
public virtual ActionResult LogOff() { FormsAuthentication.SignOut(); foreach (var cookie in Request.Cookies.AllKeys) { Request.Cookies.Remove(cookie); } foreach (var cookie in Response.Cookies.AllKeys) { Response.Cookies.Remove(cookie); } return RedirectToAction(MVC.Home.Index()); }
经过大量的搜索后,这对我有用.我希望它有所帮助.
public ActionResult LogOff() { AuthenticationManager.SignOut(); HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null); return RedirectToAction("Index", "Home"); }