正确删除服务器端cookie的方法

时间:2011-03-12 22:30:55

标签: http cookies

对于我的身份验证过程,我在用户登录时创建一个唯一令牌,并将其放入用于身份验证的cookie中。

所以我会从服务器发送这样的东西:

Set-Cookie: token=$2a$12$T94df7ArHkpkX7RGYndcq.fKU.oRlkVLOkCBNrMilaSWnTcWtCfJC; path=/;

适用于所有浏览器。然后,为了删除cookie,我发送了一个类似的cookie,其中expires字段设置为1970年1月1日

Set-Cookie: token=$2a$12$T94df7ArHkpkX7RGYndcq.fKU.oRlkVLOkCBNrMilaSWnTcWtCfJC; path=/; expires=Thu, Jan 01 1970 00:00:00 UTC; 

这在Firefox上运行正常,但不会删除IE或Safari上的cookie。

那么删除cookie的最佳方法是什么(最好不使用JavaScript)?过去设定的过期方法看起来很笨重。还有为什么这在FF中工作但在IE或Safari中不起作用?

5 个答案:

答案 0 :(得分:182)

发送附加; expires的相同cookie值不会破坏cookie。

通过设置空值来使Cookie无效,并且还包含expires字段:

Set-Cookie: token=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT

请注意,您无法强制所有浏览器删除Cookie。客户端可以配置浏览器,使cookie保持不变,即使它已过期。如上所述设置值可以解决这个问题。

答案 1 :(得分:12)

设置"到期"过去的日期是删除cookie的标准方法。

您的问题可能是因为日期格式不是传统的。 IE可能只期待GMT。

答案 2 :(得分:9)

在我撰写此答案时,accepted answer to this question似乎表明浏览器在收到Expires值为过去的替换cookie时不需要删除cookie。该说法是错误的。将Expires设置为过去是删除Cookie的标准且符合规范的方式,规范要求用​​户代理遵守该规范。

过去使用Expires属性删除cookie是正确的,并且是删除规范规定的cookie的方法。 RFC 6255的示例部分指出:

  

最后,要删除Cookie,服务器将返回Set-Cookie标头      过期日期为过去的日期。服务器将成功      仅在路径和域属性位于      Set-Cookie标头与Cookie为      已创建。

用户代理要求部分包括以下要求,这些要求共同作用,如果用户代理接收到一个具有相同名称的新cookie,且其有效期在过去

  
      
  1. 如果[在接收新cookie时] cookie存储区包含与新创建的cookie具有相同名称,域和路径的cookie:

         
        
    1. ...
    2.   
    3. ...
    4.   
    5. 更新新创建的cookie的创建时间以匹配旧cookie的创建时间。
    6.   
    7. 从cookie存储区中删除旧cookie。
    8.   
  2.   
  3. 将新创建的cookie插入cookie存储。

  4.   
     

如果Cookie的过期日期为过去,则Cookie会“过期”。

     

用户代理必须从Cookie存储中逐出所有过期的Cookie      Cookie存储区中是否存在过期的Cookie。

上面的点11-3、11-4和12一起表示,当接收到具有相同名称,域和路径的新cookie时,必须删除旧的cookie并将其替换为新的cookie。最后,关于cookie过期的问题进一步指出,完成此操作后,必须立即撤消 new cookie。在这一点上,规范没有为浏览器提供回旋余地。如果浏览器向用户提供禁用cookie过期的选项,如公认的答案表明某些浏览器会这样做,则将违反规范。 (这种功能也几乎没有用,据我所知它在任何浏览器中都不存在。)

那么,为什么这个问题的OP观察到这种方法失败了?尽管我没有清除Internet Explorer的副本来检查其行为,但我怀疑这是因为OP的Expires值格式错误!他们使用了这个值:

expires=Thu, Jan 01 1970 00:00:00 UTC;

但是,从语法上讲,这在两个方面都是无效的。

规范的syntax section规定Expires属性的值必须为

  

rfc1123-日期,在[RFC2616], Section 3.3.1

中定义

在上面的第二个链接之后,我们找到了以下格式的示例:

Sun, 06 Nov 1994 08:49:37 GMT

发现语法定义...

  1. 要求日期以日期日期年格式而不是问题提问者使用的日期日期年格式

    具体来说,它对rfc1123-date的定义如下:

    rfc1123-date = wkday "," SP date1 SP time SP "GMT"
    

    并这样定义date1

    date1        = 2DIGIT SP month SP 4DIGIT
                 ; day month year (e.g., 02 Jun 1982)
    

  1. 不允许UTC作为时区。

    该规范包含以下有关此格式可接受的时区偏移的声明:

      

    所有HTTP日期/时间戳都必须毫无例外地以格林威治标准时间(GMT)表示。

    更重要的是,如果我们深入研究此日期时间格式的原始规范,我们会发现https://tools.ietf.org/html/rfc822在其初始规范中,Syntax section将“ UT”(表示“通用时间”)列为可能的值,但 not 并没有将非UTC(世界标准时间)列出为有效值。据我所知,以这种日期格式使用“ UTC”从未有效。 1982年首次指定格式时,它不是有效值,并且HTTP规范通过严格使用 more 格式的严格限制版本,禁止使用除“ GMT”。

如果问题提问者使用的是Expires属性,例如 this ,则:

expires=Thu, 01 Jan 1970 00:00:00 GMT;

那么大概就可以了。

答案 3 :(得分:5)

使用 最大年龄= -1 而不是“过期”。它的语法更短,语法也不太挑剔,而且无论如何,Max-Age都优先于Expires。

答案 4 :(得分:-1)

对于GlassFish Jersey JAX-RS实施,我已经通过描述所有通用参数的通用方法解决了此问题。至少三个参数必须相等:name(=“ name”),path(=“ /”)和domain(= null):

public static NewCookie createDomainCookie(String value, int maxAgeInMinutes) {
    ZonedDateTime time = ZonedDateTime.now().plusMinutes(maxAgeInMinutes);
    Date expiry = time.toInstant().toEpochMilli();
    NewCookie newCookie = new NewCookie("name", value, "/", null, Cookie.DEFAULT_VERSION,null, maxAgeInMinutes*60, expiry, false, false);
    return newCookie;
}

并使用它来设置cookie的常用方法:

NewCookie domainNewCookie = RsCookieHelper.createDomainCookie(token, 60);
Response res = Response.status(Response.Status.OK).cookie(domainNewCookie).build();

并删除co​​okie:

NewCookie domainNewCookie = RsCookieHelper.createDomainCookie("", 0);
Response res = Response.status(Response.Status.OK).cookie(domainNewCookie).build();