对此我的头撞得太久了。如何防止用户在使用 FormsAuthentication.SignOut 注销后浏览网站页面?我希望这样做:

FormsAuthentication.SignOut();
Session.Abandon();
FormsAuthentication.RedirectToLoginPage();

但事实并非如此。如果我直接输入 URL,我仍然可以浏览到该页面。我已经有一段时间没有使用自己的安全性了,所以我忘记了为什么这不起作用。

有帮助吗?

解决方案

用户仍然可以浏览您的网站,因为在您调用 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参考

其他提示

听起来像你没有正确设置你的web.config授权部分。请参阅下面的示例。

<authentication mode="Forms">
  <forms name="MyCookie" loginUrl="Login.aspx" protection="All" timeout="90" slidingExpiration="true"></forms>
</authentication>
<authorization>
  <deny users="?" />
</authorization>

使用 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,或者键入它,可以从浏览器的缓存中获取页面,并且永远不会返回服务器来检查身份验证/授权。解决方法是在每个页面的Page_Load事件或基页的OnLoad()中阻止客户端缓存:

Response.Cache.SetCacheability(HttpCacheability.NoCache);

您可能还想致电:

Response.Cache.SetNoStore();

我之前也在努力解决这个问题。

以下是对似乎正在发生的事情的类比......新访客Joe来到网站并使用FormsAuthentication通过登录页面登录。 ASP.NET为Joe生成一个新标识,并为他提供一个cookie。那个饼干就像是房子的钥匙,只要乔带着那把钥匙回来,他就可以打开锁。每个访问者都会获得一个新密钥和一个新锁。

当调用 FormsAuthentication.SignOut()时,系统会告诉Joe丢失密钥。通常情况下,这是有效的,因为乔不再拥有钥匙,他无法进入。

但是,如果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");
}

<li class="page-scroll">@Html.ActionLink("Log off", "LogOff", "Account")</li>

您发布的代码看起来应该正确删除表单身份验证令牌,因此有问题的文件夹/页面可能实际上没有受到保护。

您是否确认在登录之前无法访问这些页面?

您可以发布您正在使用的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);
        }

虽然浏览器上的后退功能把我带回来并显示了安全菜单(我还在努力)但我无法做任何在应用程序中受到保护的事情。

希望这有帮助

我在这个帖子中尝试了大多数答案,没有运气。结束了这个:

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

此答案在技术上与Khosro.Pakmanesh完全相同。我发布它是为了澄清他的答案与这个帖子上的其他答案有何不同,以及在哪个用例中可以使用它。

一般来说,要清除用户会话,请执行

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

当我设置身份验证&gt;时,这开始发生在我身上表格&gt; Web.config 中的路径属性。删除修复问题,并简单的 FormsAuthentication.SignOut(); 再次删除了cookie。

可能是您从一个子域(sub1.domain.com)登录,然后尝试从其他子域(www.domain.com)注销。

我遇到了同样的问题,SignOut()似乎无法正确删除故障单。但仅在特定情况下,其他一些逻辑导致重定向。在我删除了第二次重定向(替换为错误消息)之后,问题就消失了。

问题必定是页面在错误的时间重定向,因此不会触发身份验证。

我现在遇到类似的问题,我相信我的案例以及原始海报的问题是因为重定向。默认情况下,Response.Redirect会导致异常,该异常会立即冒出,直到被捕获并立即执行重定向,我猜这是阻止修改后的cookie集合传递给客户端。如果您修改要使用的代码:

Response.Redirect("url", false);

这可以防止异常,并且似乎允许将cookie正确地发送回客户端。

按下登录时尝试发送会话变量。 在欢迎页面上,首先在页面加载或Init事件中检查该会话是否为空:

if(Session["UserID"] == null || Session["UserID"] == "")
{
    Response.Redirect("Login.aspx");
}

对我来说,以下方法有效。我想如果在“FormsAuthentication.SignOut()”之后有任何错误。声明,SingOut不起作用。

public ActionResult SignOut()
    {
        if (Request.IsAuthenticated)
        {
            FormsAuthentication.SignOut();

            return Redirect("~/");
        }
        return View();
     }

您是否正在使用IE测试/看到此行为? IE可能正在从缓存中提供这些页面。众所周知,很难让IE刷新它的缓存,所以在许多情况下,即使你注销后,也要输入其中一个“安全”的网址。页面将显示之前的缓存内容。

(即使你以不同的用户身份登录,我也看到了这种行为,IE显示页面顶部的“欢迎”栏,使用旧用户的用户名。现在,通常重新加载会更新它,但如果它持续存在,它仍然可能是一个缓存问题。)

执行Session.abandon()并销毁cookie非常有用。我正在使用mvc3,如果您访问受保护的页面,注销并通过浏览器历史记录,则看起来会出现问题。没什么大不了的,但还是有点讨厌。

尝试通过我的网络应用上的链接以正确的方式工作。

将其设置为不进行浏览器缓存可能是最佳选择。

对于MVC,这对我有用:

        public ActionResult LogOff()
        {
            FormsAuthentication.SignOut();
            return Redirect(FormsAuthentication.GetRedirectUrl(User.Identity.Name, true));
        }

我想添加一些信息来帮助理解问题。表单身份验证允许将用户数据存储在cookie中或URL的查询字符串中。您可以在web.config文件中配置您的站点支持的方法。

根据到微软

  

SignOut方法删除表单身份验证票证信息   来自Cookie或网址 ,如果CookiesSupported为false

与此同时,他们说

  

其中一个HttpCookieMode值指示是否   应用程序配置为无cookie表单身份验证。的    默认为UseDeviceProfile

最后,关于UseDeviceProfile,他们说

  

如果将CookieMode属性设置为UseDeviceProfile,则    如果 的浏览器,CookiesSupported属性将返回true    当前请求支持Cookie和使用Cookie重定向 ;   否则,CookiesSupported属性将返回false。

将所有内容拼凑在一起,具体取决于用户的浏览器,默认配置可能导致CookiesSupported true ,这意味着SignOut方法不会从cookie中清除票证。这似乎是违反直觉的,我不知道它为什么会这样 - 我希望SignOut在任何情况下实际签署用户。

使SignOut单独工作的一种方法是将cookie模式更改为“UseCookies”; (即必须使用cookie)在web.config文件中:

<authentication mode="Forms">
  <forms loginUrl="~/Account/SignIn" cookieless="UseCookies"/>
</authentication>

根据我的测试,这样做会使SignOut以您自己的网站为代价自行运行,现在要求Cookie正常运行。

请注意,如果来自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。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top