我的头撞了这么长时间。如何防止用户在使用FormsAuthentication.SignOut注销后浏览网站的页面?我希望这样做:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
但事实并非如此。如果我直接输入URL,我仍然可以浏览到该页面。我有一段时间没有使用自己的安全性,所以我忘记了为什么这不起作用。
答案 0 :(得分:198)
用户仍然可以浏览您的网站,因为在您致电FormsAuthentication.SignOut()
时不会清除Cookie,并且会在每次新请求时对其进行身份验证。在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 Reference
答案 1 :(得分:20)
听起来像你没有正确设置你的web.config授权部分。请参阅下面的示例。
<authentication mode="Forms">
<forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
答案 2 :(得分:20)
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" );
}
答案 3 :(得分:12)
这里的关键是你说“如果我直接输入网址......”。
默认情况下,在表单身份验证下,浏览器会为用户缓存页面。因此,直接从浏览器地址框下拉列表中选择一个URL,或者键入它,可以从浏览器的缓存中获取页面,并且永远不会返回服务器来检查身份验证/授权。解决方法是在每个页面的Page_Load事件或基页的OnLoad()中阻止客户端缓存:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
您可能还想致电:
Response.Cache.SetNoStore();
答案 4 :(得分:11)
我之前也在努力解决这个问题。
以下是对似乎正在发生的事情的类比......新访问者Joe来到网站并使用FormsAuthentication通过登录页面登录。 ASP.NET为Joe生成一个新标识,并为他提供一个cookie。那个饼干就像是房子的钥匙,只要乔带着那把钥匙回来,他就可以打开锁。每个访问者都会获得一个新密钥和一个新锁。
当调用FormsAuthentication.SignOut()
时,系统会告诉Joe丢失密钥。通常情况下,这是有效的,因为乔不再拥有钥匙,他无法进入。
但是,如果Joe回来了,并且确实丢失了密钥,那么他就会被让回来!
据我所知,没有办法告诉ASP.NET更改门锁!
我可以采用的方法是在Session变量中记住Joe的名字。当他退出时,我放弃了会议,所以我不再有他的名字了。稍后,为了检查他是否被允许,我只是将他的Identity.Name与当前会话的内容进行比较,如果它们不匹配,则他不是有效的访问者。
简而言之,对于网站,请不要依赖User.Identity.IsAuthenticated
而不检查会话变量!
答案 5 :(得分:6)
经过大量搜索后,这对我有用。我希望它有所帮助。
public ActionResult LogOff()
{
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
return RedirectToAction("Index", "Home");
}
<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>
答案 6 :(得分:6)
这对我有用
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());
}
答案 7 :(得分:3)
一般来说,要清除用户会话,请执行
HttpContext.Session.Abandon();
FormsAuthentication.SignOut();
将有效地注销用户。 然而,如果在同一个请求中,您需要检查Request.isAuthenticated
(例如,可能经常在授权过滤器中发生),那么您会发现
Request.isAuthenticated == true
即使_后来HttpContext.Session.Abandon()
和FormsAuthentication.SignOut()
。
唯一有效的方法是做
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
有效设置Request.isAuthenticated = false
。
答案 8 :(得分:3)
您发布的代码看起来应该正确删除表单身份验证令牌,因此有问题的文件夹/页面可能实际上没有受到保护。
您是否确认在登录之前无法访问这些页面?
您可以发布您正在使用的web.config设置和登录代码吗?
答案 9 :(得分:3)
我在这个帖子中尝试了大多数答案,没有运气。结束了这个:
protected void btnLogout_Click(object sender, EventArgs e)
{
FormsAuthentication.Initialize();
var fat = new FormsAuthenticationTicket(1, "", DateTime.Now, DateTime.Now.AddMinutes(-30), false, string.Empty, FormsAuthentication.FormsCookiePath);
Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(fat)));
FormsAuthentication.RedirectToLoginPage();
}
答案 10 :(得分:3)
我刚刚尝试了一些建议,当我能够使用浏览器后退按钮时,当我点击菜单选项时,[ActionResult]的[Authorize]令牌将我发送回登录屏幕。< / p>
这是我的退出代码:
FormsAuthentication.SignOut();
Response.Cookies.Remove(FormsAuthentication.FormsCookieName);
Response.Cache.SetExpires(DateTime.Now.AddSeconds(-1));
HttpCookie cookie = HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
cookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(cookie);
}
虽然浏览器上的后退功能把我带回来并显示了安全菜单(我还在努力)但我无法做任何在应用程序中受到保护的事情。
希望这有帮助
答案 11 :(得分:3)
我一直在为所有的Pages编写基类,我遇到了同样的问题。 我有类似下面的代码,它没有用。通过跟踪,控制从RedirectToLoginPage()语句传递到下一行而不被重定向。
if (_requiresAuthentication)
{
if (!User.Identity.IsAuthenticated)
FormsAuthentication.RedirectToLoginPage();
// check authorization for restricted pages only
if (_isRestrictedPage) AuthorizePageAndButtons();
}
我发现有两种解决方案。 要么修改FormsAuthentication.RedirectToLoginPage();是
if (!User.Identity.IsAuthenticated)
Response.Redirect(FormsAuthentication.LoginUrl);
或者通过添加
来修改web.config<authorization>
<deny users="?" />
</authorization>
在第二种情况下,在跟踪时,控件未到达请求的页面。在到达断点之前,它已被立即重定向到登录URL。 因此,SignOut()方法不是问题,重定向方法就是那个。
我希望这可以帮助某人
此致
答案 12 :(得分:2)
当我设置身份验证&gt;时,这开始发生在我身上表格&gt; Web.config
中的路径属性。删除它解决了问题,而简单的FormsAuthentication.SignOut();
再次删除了Cookie。
答案 13 :(得分:1)
我现在遇到类似的问题,我相信我的案例以及原始海报的问题是因为重定向。默认情况下,Response.Redirect会导致异常,该异常会立即冒出,直到被捕获并立即执行重定向,我猜这是阻止修改后的cookie集合传递给客户端。如果您修改要使用的代码:
Response.Redirect("url", false);
这可以防止异常,并且似乎允许将cookie正确地发送回客户端。
答案 14 :(得分:1)
我遇到了同样的问题,SignOut()似乎无法正确删除故障单。但仅在特定情况下,其他一些逻辑导致重定向。在我删除了第二次重定向(替换为错误消息)之后,问题就消失了。
问题必定是页面在错误的时间重定向,因此不会触发身份验证。
答案 15 :(得分:1)
按下登录时尝试发送会话变量。 在欢迎页面上,首先在页面加载或Init事件中检查该会话是否为空:
if(Session["UserID"] == null || Session["UserID"] == "")
{
Response.Redirect("Login.aspx");
}
答案 16 :(得分:1)
可能是您从一个子域(sub1.domain.com)登录,然后尝试从其他子域(www.domain.com)注销。
答案 17 :(得分:1)
对我来说,以下方法有效。我想如果&#34; FormsAuthentication.SignOut()&#34;之后有任何错误。声明,SingOut没有工作。
public ActionResult SignOut()
{
if (Request.IsAuthenticated)
{
FormsAuthentication.SignOut();
return Redirect("~/");
}
return View();
}
答案 18 :(得分:0)
执行Session.abandon()并销毁cookie非常有用。我正在使用mvc3,如果您访问受保护的页面,注销并通过浏览器历史记录,则看起来会出现问题。没什么大不了的,但还是有点讨厌。
尝试通过我的网络应用上的链接以正确的方式工作。
将其设置为不进行浏览器缓存可能是最佳选择。
答案 19 :(得分:0)
对于MVC,这对我有用:
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
}
答案 20 :(得分:0)
我想添加一些信息来帮助理解问题。表单身份验证允许将用户数据存储在cookie中或URL的查询字符串中。您可以在web.config文件中配置您的站点支持的方法。
SignOut方法删除表单身份验证票证信息 来自Cookie或网址 ,如果CookiesSupported为false 。
与此同时,they say:
其中一个HttpCookieMode值指示是否 应用程序配置为无cookie表单身份验证。的 的 强> 默认为UseDeviceProfile 。
最后,关于UseDeviceProfile,they say:
如果将CookieMode属性设置为UseDeviceProfile,则 如果 的浏览器,CookiesSupported属性将返回true 当前请求支持Cookie和使用Cookie重定向 ; 否则,CookiesSupported属性将返回false。
将所有内容拼凑在一起,具体取决于用户的浏览器,默认配置可能导致CookiesSupported true ,这意味着SignOut方法不会从cookie中清除票证。这似乎是违反直觉的,我不知道它为什么会这样 - 我希望SignOut在任何情况下实际签署用户。
使SignOut单独工作的一种方法是在web.config文件中将cookie模式更改为“UseCookies”(即需要cookie):
<authentication mode="Forms">
<forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>
根据我的测试,这样做会使SignOut以您自己的网站为代价自行运行,现在要求Cookie正常运行。
答案 21 :(得分:0)
您是否正在使用IE测试/看到此行为? IE可能正在从缓存中提供这些页面。众所周知,很难让IE刷新它的缓存,所以在很多情况下,即使你注销后,键入其中一个“安全”页面的URL也会显示之前的缓存内容。
(即使你以不同的用户身份登录,我也看到了这种行为,IE显示页面顶部的“欢迎”栏,使用旧用户的用户名。现在,通常重新加载会更新它,但是如果它是持久的,它仍然可能是一个缓存问题。)
答案 22 :(得分:-1)
请注意,如果来自STS的wsignoutcleanup消息与来自IIS的应用程序名称的url不匹配,WIF 拒绝告诉浏览器清理Cookie,我的意思是案例敏感。 WIF以绿色OK检查响应,但不发送命令删除浏览器的cookie。
因此,您需要注意网址的区分大小写。
例如,ThinkTecture Identity Server将访问RP的URL保存在一个cookie中,但它使所有这些都小写。 WIF将以小写形式接收wsignoutcleanup消息,并将其与IIS中的应用程序名称进行比较。如果不匹配,则不删除cookie,但会向浏览器报告OK。因此,对于这个Identity Server,我需要以小写形式编写web.config中的所有URL和IIS中的所有应用程序名称,以避免此类问题。
如果您的应用程序位于STS子域之外,请不要忘记在浏览器中允许第三方cookie,否则即使WIF告诉他,浏览器也不会删除cookie。