我把头砸得太久了。使用FormsAuthentication.SignOut注销后,如何防止用户浏览网站的页面?我希望这样做:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
但事实并非如此。如果直接输入URL,我仍然可以浏览到该页面。我已经有一段时间没有使用过自助式安全了,所以我忘记了为什么这不起作用。
我把头砸得太久了。使用FormsAuthentication.SignOut注销后,如何防止用户浏览网站的页面?我希望这样做:
FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();
但事实并非如此。如果直接输入URL,我仍然可以浏览到该页面。我已经有一段时间没有使用过自助式安全了,所以我忘记了为什么这不起作用。
Answers:
用户仍然可以浏览您的网站,因为在您致电时Cookie不会被清除,FormsAuthentication.SignOut()
并且每次新请求都会对它们进行身份验证。在MS文档中,会说cookie将被清除,但是不会清除,是吗?与完全相同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参考。
使用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给出了上面的示例,说明如何在注销后防止缓存:
您需要通过Response使客户端上的缓存无效。
// 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" );
}
SessionStateSection sessionStateSection = (SessionStateSection)WebConfigurationManager.GetSection("system.web/sessionState"); HttpCookie sessionCookie = new HttpCookie(sessionStateSection.CookieName, "");
。通常,会话cookie名称不是"ASP.NET_SessionId"
。
在我看来,您没有在中正确设置web.config授权部分。请参阅下面的示例。
<authentication mode="Forms">
<forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
我以前也为此感到苦恼。
这是似乎正在发生的事情的类比...新访客Joe来到该站点,并使用FormsAuthentication通过登录页面登录。ASP.NET为Joe生成一个新的身份,并给他一个cookie。那个小甜饼就像房子的钥匙,只要乔用那个钥匙回来,他就可以打开锁。每个访问者都有一个新的密钥和一个新的锁可以使用。
当FormsAuthentication.SignOut()
被调用时,系统会告诉乔失去的关键。通常,这可行,因为Joe不再拥有密钥,所以他无法进入。
但是,如果Joe回来并且确实丢失了钥匙,他将被放回原处!
据我所知,没有办法告诉ASP.NET更改门上的锁!
我可以忍受的方式是在Session变量中记住Joe的名字。当他注销时,我放弃了Session,所以不再有他的名字。稍后,要检查是否允许他进入,我只需将其Identity.Name与当前会话中的内容进行比较,如果它们不匹配,则他不是有效的访客。
简而言之,对于一个网站,不要不User.Identity.IsAuthenticated
检查会话变量就不要依赖它!
经过大量的搜索,最终这对我有用。希望对您有所帮助。
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>
这对我有用
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());
}
您发布的代码看起来应该正确删除了表单身份验证令牌,因此所讨论的文件夹/页面可能实际上未受到保护。
您是否已确认登录之前无法访问页面?
您可以发布您正在使用的web.config设置和登录代码吗?
我一直在为我的所有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()方法不是问题,重定向方法是唯一的问题。
我希望可以帮助某人
问候
我只是在这里尝试了一些建议,虽然可以使用浏览器的后退按钮,但是当我单击菜单选项时,该[ActionResult]的[Authorize]令牌立即将我发送回了登录屏幕。
这是我的注销代码:
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);
}
尽管浏览器上的后退功能使我退回并显示了安全菜单(我仍在处理该菜单),但我无法执行该应用程序中已保护的任何操作。
希望这可以帮助
<deny users="?" />
有用的解决方案(不需要在web.config中使用)
我已经尝试过该线程中的大多数答案,没有运气。最终这样:
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();
}
在这里找到它:http : //forums.asp.net/t/1306526.aspx/1
一般来说要清除用户会话,在做
HttpContext.Session.Abandon();
FormsAuthentication.SignOut();
将有效注销用户。但是,如果在同一请求中需要检查Request.isAuthenticated
(例如,在“授权过滤器”中可能经常发生),那么您会发现
Request.isAuthenticated == true
甚至_after你做HttpContext.Session.Abandon()
和FormsAuthentication.SignOut()
。
唯一有效的是做
AuthenticationManager.SignOut();
HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
有效地设置Request.isAuthenticated = false
。
我只是遇到了同样的问题,其中SignOut()似乎无法正确删除票证。但仅在特定情况下,其中某些其他逻辑导致重定向。我删除了第二个重定向(将其替换为错误消息)后,问题消失了。
问题一定是页面在错误的时间重定向,因此没有触发身份验证。
我现在有一个类似的问题,我认为我的问题以及原始张贴者的问题都是由于重定向。默认情况下,Response.Redirect会导致一个异常,该异常立即冒泡直到被捕获并立即执行重定向,我猜测这将阻止修改后的Cookie集合向下传递给客户端。如果您修改代码以使用:
Response.Redirect("url", false);
这样可以防止出现异常,并且似乎允许将Cookie正确发送回客户端。
我想添加一些信息以帮助理解问题。表单身份验证允许将用户数据存储在cookie或URL的查询字符串中。您的站点支持的方法可以在web.config文件中进行配置。
如果CookiesSupported为false,则 SignOut方法将从cookie或URL中删除表单身份验证票证信息。
同时,他们说:
HttpCookieMode值之一,该值指示是否为无cookie表单身份验证配置了应用程序。在 默认情况下是UseDeviceProfile。
最后,关于UseDeviceProfile,他们说:
如果CookieMode属性设置为UseDeviceProfile,则如果 当前请求的浏览器同时支持cookie和使用cookie的重定向,则 CookiesSupported属性将返回true。否则,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才能正常运行。
请注意,如果STS中的wsignoutcleanup消息与IIS中的应用程序名称不匹配,则WIF 拒绝告诉浏览器清理cookie,我的意思是CASE SENSITIVE。WIF会以绿色的OK确认回应,但不会将删除Cookie的命令发送到浏览器。
因此,您需要注意网址的区分大小写。
例如,ThinkTecture Identity Server将访问的RP的URL保存在一个cookie中,但是使它们全部变为小写。WIF将收到小写的wsignoutcleanup消息,并将其与IIS中的应用程序名称进行比较。如果不匹配,它将不删除任何cookie,但会向浏览器报告“确定”。因此,对于此Identity Server,我需要将所有URL都写在web.config中,并将所有应用程序名称写在IIS中,以小写形式,以避免出现此类问题。
另外,如果您的应用程序位于STS子域之外,也不要忘记在浏览器中允许第三方cookie,否则即使WIF告知,浏览器也不会删除这些cookie。