通过Set-Cookie注销失败

时间:2013-11-22 15:09:19

标签: authentication cookies logout

我们不久前将我们的网站迁移到了一个新的托管服务商,并且经常出现人们无法注销的问题。不确定这是否与托管环境或代码更改有关。

这是相关位的Wireshark日志 - 所有这些都发生在同一个TCP流中。

  1. 来自浏览器的退出请求(请注意身份验证Cookie):

    GET /cirrus/logout HTTP/1.1
    
    Host: subdomain.domain.com
    
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    
    Accept-Language: en-US,en;q=0.5
    
    Accept-Encoding: gzip, deflate
    
    Referer: http://subdomain.domain.com/cirrus/CA/Admin/AccountSwitch
    
    Cookie:  USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye
    
    X-LogDigger-CliVer: client-firefox 2.1.5
    
    X-LogDigger: logme=0&reqid=fda96ee5-2db4-f543-81b5-64bdb022d358&
    
    Connection: keep-alive
    
  2. 服务器响应。它清除cookie值并重定向

    HTTP/1.1 302 Found
    
    Server: nginx
    
    Date: Fri, 22 Nov 2013 14:40:22 GMT
    
    Content-Type: text/html; charset=utf-8
    
    Content-Length: 124
    
    Connection: keep-alive
    
    Cache-Control: private, no-cache="Set-Cookie"
    
    Location: /cirrus
    
    Set-Cookie: USER.AUTH=; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus
    
    X-Powered-By: ASP.NET
    
    X-UA-Compatible: chrome=IE8
    
    
    
    <html><head><title>Object moved</title></head><body>
    
    <h2>Object moved to <a href="/cirrus">here</a>.</h2>
    
    </body></html>
    
  3. 浏览器遵循重定向,但使用旧的cookie值:

    GET /cirrus HTTP/1.1
    
    Host: subdomain.domain.com
    
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:26.0) Gecko/20100101 Firefox/26.0
    
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    
    Accept-Language: en-US,en;q=0.5
    
    Accept-Encoding: gzip, deflate
    
    Referer: http://subdomain.domain.com/cirrus/CA/Admin/AccountSwitch
    
    Cookie: USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye
    
    X-LogDigger-CliVer: client-firefox 2.1.5
    
    X-LogDigger: logme=0&reqid=0052e1e1-2306-d64d-a308-20f9fce4702e&
    
    Connection: keep-alive
    
  4. Set-Cookie标头中是否有任何明显的缺失可能会阻止浏览器删除cookie?

    要更改现有Cookie的值,以下Cookie参数必须匹配:

    • 姓名
    • 路径

    名称和路径设置为explecitely,域不是。这可能是问题吗?

    编辑:因为有人问过为什么过去设定过期日期,所以背景更多。 这是对AppHarbor Security插件的略微修改:https://github.com/appharbor/AppHarbor.Web.Security 修改是包括cookie的路径。请在此处找到修改后的注销方法:

    public void SignOut(string path)
        {
            _context.Response.Cookies.Remove(_configuration.CookieName);
            _context.Response.Cookies.Add(new HttpCookie(_configuration.CookieName, "")
            {
                Expires = DateTime.UtcNow.AddMonths(-100),
                Path = path
            });
        }
    

    过去的过期日期由AppHarbor插件完成,这是常见做法。见http://msdn.microsoft.com/en-us/library/ms178195(v=vs.100).aspx

3 个答案:

答案 0 :(得分:1)

我猜测历史到期日会导致整个Set-Cookie行被忽略(为什么设置一个8年前过期的cookie?)。

expires=Fri, 22-Jul-2005

答案 1 :(得分:1)

我们在过去删除Cookie时遇到了问题,是的,域和路径必须与您尝试删除的Cookie的域和路径相匹配。

尝试在HttpCookie

中设置正确的域和路径

答案 2 :(得分:1)

很棒的问题和优秀的笔记。我最近也遇到过这个问题。

除了您应该做的事情之外,还有一种自动防范方法:

  • 过去设定过期时间。
  • 设置路径域。
  • 将伪造的数据放入要删除的Cookie中!

Set-Cookie: USER.AUTH=invalid; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus; domain=subdomain.domain.com

故障安全方法如下:

最后为所有Cookie添加一个特殊字符串。除非该字符串存在,否则拒绝cookie并强制重置它。例如,所有新cookie必须如下所示:

Set-Cookie: USER.AUTH=AOvDEjH3w6xIxUC0sYNOAQR5BZ7pPmEF0RMxqohERN87Ti03Eqxd7rQC/BveqmaszmFg8QoSonP+Z+mtQQivKpvloFsQYretYKR8ENubj+moUBF479K5e4albKxS9mBEWT5Xy/XCnEyCPqLASGLY09ywkmIilNU1Ox4J3fCtYXHelE/hyzuKe9y3ui5AKEbbGs3sN9q1zYjVjHKKiNIGaHvjJ2zn7ZUs042B82Jc9RHzt0JW8dnnrl3mAkN1lJQogtlG+ynQSCyQD8YzgO8IpOnSXLJLaCMGMQcvSyX4YKJU/9sxgA5r5cZVCkHLsReS3eIJtXoxktMO6nxVZJY6MX1YwuJOgLRQvwBy9FFnQ6ye|1386510233; expires=Fri, 22-Jul-2005 14:40:17 GMT; path=/cirrus; domain=subdomain.domain.com

注意更改:存储在USER.AUTH中的极长字符串以|1386510233结尾,这是设置cookie时的unix时期。

这为cookie解析添加了一个简单的额外步骤。现在你需要测试|的存在并丢弃unix时代,除非你想知道cookie何时被设置。为了使其更快,您可以检查string[length-10]==|而不是解析整个字符串。在我这样做的过程中,我将字符串拆分为|并在拆分后检查两个值。这绕过了一个由两部分组成的解析过程,但这个方面是特定于语言的,当涉及到你选择的策略时,它实际上只是优先考虑。如果您打算丢弃该值,只需检查您希望|所在的特定索引。

将来如果再次更改主机,您可以测试该unix时期并拒绝早于特定时间点的cookie。这最多会为您的cookie处理程序添加两个额外的进程:删除|unixepoch,如果需要,在再次更改主机时检查该时间是否拒绝cookie。这会为页面加载增加约0.001s或更少。与客户服务失败和大规模脑损伤相比,这是值得的。

您的新Cookie策略允许您在没有|unixepoch的情况下轻松拒绝所有Cookie,因为您知道它们是旧Cookie。是的,人们可能会抱怨这种方法,但这是真正了解cookie有效的唯一方法。您不能依赖客户端为您提供有效的cookie。除非你想存储大量数据,否则你无法记录每一个cookie。如果您每次都存储每个cookie并进行检查,那么在此策略中可以将0.01s添加到页面加载而不是0.001s,因此仓库路线不值得。

另一种方法是使用USER.AUTHENTICATION而不是USER.AUTH作为新的Cookie值,但这可能更具侵略性。如果/当你再次更换主机时,你没有从上面所说的内容中获益。

祝你过渡顺利。我希望你能解决这个问题。使用上面的策略,我能够。