【问题标题】:Asp.net get rid of session on server on logout after clearing cookies, session, and formsauth清除 cookie、会话和 formauth 后,Asp.net 在注销时摆脱服务器上的会话
【发布时间】:2014-10-30 18:34:01
【问题描述】:

我遇到了 asp.net 的安全问题。注销时,我想确保会话被销毁,以便有人无法获取相同的 sessionid 和 auth cookie 并在那里编辑 cookie,并且服务器仍然响应会话。

FormsAuthentication.SignOut();
Session.Abandon();
Session.RemoveAll();
Session.Clear(); 

我也试过给客户端写新的cookies

// clear authentication cookie
HttpCookie cookie1 = new HttpCookie(FormsAuthentication.FormsCookieName, "");
cookie1.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie1);

HttpCookie cookie2 = new HttpCookie("ASP.NET_SessionId", "");
cookie2.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(cookie2);

我尝试以不同的顺序使用以下内容,但仍然没有骰子。如果我使用原始 sessionid 和 Auth cookie,我仍然可以登录。我希望服务器在我注销时完全忘记那个 sessionid。这甚至可能吗?

【问题讨论】:

标签: c# asp.net session cookies


【解决方案1】:

在服务器端,无法永久清除身份验证会话。您可以清除 cookie,但如果有人复制了它,他们可以简单地重新使用它,然后他们就可以访问该站点。 Auth cookie 是加密的验证票,这意味着站点会对其进行解密,并验证它们是否正确解密并且未过期。如果是这种情况,那么 auth cookie 是有效的。

不幸的是,除了使用较短的过期值并在滑动窗口上更新过期日期外,没有其他办法,但这意味着如果用户空闲几分钟,他们将不得不再次登录。

没有与身份验证票证关联的“会话 ID”,尽管您当然可以生成一个唯一 ID 并将其存储在票证中,然后将该 ID 存储在服务器上并在每个请求上进行比较以添加额外的一层安全。当你想杀死那个 cookie 时,你清除服务器上的任何 ID,他们就无法再登录,即使票证在其他方面是有效的。

另一方面,会话 cookie 确实具有 id,并且与映射到该 ID 的内部存储相关联,因此当您清除会话时,您也会删除存储...如果您重用该 cookie,那么它只会获得空数据.

您还可以通过始终使用加密的 cookie 和使用 HTTPS 来增加安全性。 HTTPS 不会以可以获取和重复使用它们的方式存储 cookie(它们使用 SSL 会话加密,一旦 SSL 会话完成,cookie 将无法使用)。

另一种选择是使用非持久性 cookie,它们不会存储在服务器上。虽然它们仍然可以被中间人攻击捕获。

要了解为什么无法解决该问题,您必须了解身份验证 cookie 旨在长期存在并存储在用户计算机上。当您返回时,它可能是不同的会话。因此,了解用户是否通过身份验证的唯一方法是简单地依赖于 cookie 是否可以使用服务器凭据(通常是机器密钥)解密。这意味着会话和身份验证票证之间故意没有链接。

【讨论】:

    【解决方案2】:

    服务器确实忘记了与该会话相关的所有内容,因此在您使用 Session.Clear() 时使该会话 ID 无效。

    正如msdn documentation 所说:

    从会话状态集合中删除所有键和值

    因此,即使有人使用相同的会话 ID,服务器中也不会附加任何信息。

    [编辑]

    正如 Erik Funkenbusch 所指出的,我的解决方案仅在您将身份验证信息存储在会话中时才有效(显然)。如果您的身份验证系统有特定的 cookie,这将不起作用。

    【讨论】:

    • 是的,但是对于有效会话和无效会话必须有某种授权才能在服务器上进行比较,否则任何人都可以告诉服务器他们以 Joe Smith 的身份登录
    • 否,因为所有将您标识为 Joe Smith 的信息都已删除,Session.Clear()
    • @Joanvo - 会话与身份验证无关,身份验证将您标识为 Joe Smith。
    • 我不明白为什么这被标记为接受的答案。您只是在此处清除存储在会话中的信息,这不可能是该会话是否经过身份验证的决定因素。那是没有意义的。
    • @MikeManard 它回答了我注销时服务器是否完全忘记了 sessionid 的问题
    【解决方案3】:

    确保在服务器端擦除所有会话/cookie 的非编程方式是在应用程序的 web.config 中添加(如果不存在)或更改(如果存在)机器密钥

    可以通过 IIS 管理器通过选择一个应用程序来完成,在 ASP.NET 部分选择“机器密钥”,取消选中所有复选框并点击生成密钥,然后点击应用

    请注意,这不是针对单个用户的,它会踢出所有用户。

    【讨论】:

    • 是的,我正在寻找如何在用户注销系统时从内存中清除用户
    • 我发布这个答案是因为我们想强制每个人重新登录,我们在 SO 上找到的所有解决方案都是关于修改 cookie,这不起作用,所以也许有人会从我的回答中受益,但我不知道在哪里准确回答。您的 Q 的标题似乎与我的回答最中立/相关。谢谢!
    【解决方案4】:

    如果您指向浏览器后退按钮,我使用下面的代码(vb,但您可以转换它):

    web.config:

    <sessionState timeout="20" regenerateExpiredSessionId="true"/>
    

    avsessexp.js(如果 15 分钟后不活动,则自动刷新页面):

    var BeatTimer;
        function StartCheck() {
            if (BeatTimer == null) {
                BeatTimer = setInterval("CheckBeat()", 900000);
            }
        }
    
        function CheckBeat() {
            PageMethods.PokePage();
        }
    

    并在每一页调用StartCheck函数(&lt;body onload="StarCheck();"&gt;

    在我放置的每个页面的标题中:

    <meta http-equiv="pragma" content="no-cache" />
    <meta http-equiv="cache-control" content="no-cache, no-store, max-age=0, must-revalidate" />
    <meta http-equiv="expires" content="0" />
    

    Module1.vb

    Public Sub CheckSession()
            With HttpContext.Current
                .Response.Cache.SetExpires(DateTime.UtcNow.AddSeconds(-1))
                .Response.Cache.SetCacheability(HttpCacheability.NoCache)
                .Response.Cache.SetNoStore()
                If .Session.IsNewSession = True Then LogOut()
                'there You can put some code checking is user logged, ...
            End With
        End Sub
    
        Public Sub LogOut()
            With HttpContext.Current
                .Session.RemoveAll()
                .Session.Clear()
                .Session.Abandon()
                Try
                    .Response.Cookies.Add(New System.Web.HttpCookie("ASP.NET_SessionId", ""))
                Catch ex As Exception
    
                End Try
                .Response.Redirect("Default.aspx")
            End With
        End Sub
    

    并且,在每个页面中(代码隐藏):

    <System.Web.Services.WebMethod(EnableSession:=True)> Public Shared Sub PokePage()
            CheckSession()
        End Sub
    
        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
           If Not IsPostBack Then CheckSession()
        End Sub
    

    如果您在注销后尝试单击浏览器返回按钮,CheckUser 将阻止返回上一页,并始终将用户重定向到登录页面。

    在每个页面/母版页上使用非常重要&lt;asp:ScriptManager runat="server" id="sm1" EnablePageMethods="True"&gt;&lt;asp:ScriptManager&gt;

    附言对不起我的英语不好。

    【讨论】:

      【解决方案5】:

      为会话状态执行 cookieless="true"

      【讨论】:

        猜你喜欢
        • 2014-10-30
        • 1970-01-01
        • 2012-06-04
        • 1970-01-01
        • 2019-03-16
        • 1970-01-01
        • 2015-12-26
        • 2021-03-14
        • 2018-09-24
        相关资源
        最近更新 更多