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

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

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

适用于所有浏览器。然后,为了删除一个cookie,我发送了一个类似的cookie,过期字段设置为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中不工作?


发送相同的cookie值;附加的过期不会销毁cookie。

通过设置一个空值使cookie无效,并包括一个expires字段:

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

请注意,您不能强制所有浏览器删除cookie。客户端可以对浏览器进行配置,使cookie即使过期也能保存。如上所述设置值可以解决这个问题。


将“过期日期”设置为过去的日期是删除cookie的标准方法。

您的问题可能是因为日期格式不是常规的。IE可能只期待格林尼治时间。


对于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();

删除cookie:

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

在我写这个答案的时候,这个问题的公认答案似乎表明,浏览器在收到过期值为过去的替换cookie时,不需要删除cookie。这种说法是错误的。将过期时间设置为过去时间是标准的、符合规范的删除cookie的方式,规范要求用户代理尊重它。

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

最后,为了删除一个cookie,服务器返回一个Set-Cookie报头 在过去有个截止日期。服务器将会成功 在删除cookie时,只有路径和域属性在 Set-Cookie报头与cookie存在时使用的值匹配 创建。

用户代理需求部分包括以下需求,如果用户代理接收到具有相同名称且过期的新cookie,则必须立即删除cookie

If [when receiving a new cookie] the cookie store contains a cookie with the same name, domain, and path as the newly created cookie: ... ... Update the creation-time of the newly created cookie to match the creation-time of the old-cookie. Remove the old-cookie from the cookie store. Insert the newly created cookie into the cookie store. A cookie is "expired" if the cookie has an expiry date in the past. The user agent MUST evict all expired cookies from the cookie store if, at any time, an expired cookie exists in the cookie store.

Points 11-3, 11-4, and 12 above together mean that when a new cookie is received with the same name, domain, and path, the old cookie must be expunged and replaced with the new cookie. Finally, the point below about expired cookies further dictates that after that is done, the new cookie must also be immediately evicted. The spec offers no wiggle room to browsers on this point; if a browser were to offer the user the option to disable cookie expiration, as the accepted answer suggests some browsers do, then it would be in violation of the spec. (Such a feature would also have little use, and as far as I know it does not exist in any browser.)

那么,为什么这个问题的OP观察到这种方法失败了呢?虽然我还没有打开ie浏览器来检查它的行为,但我怀疑这是因为OP的Expires值是畸形的!他们使用这个值:

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

然而,这在两个方面是语法无效的。

规范的语法部分规定Expires属性的值必须是

rfc1123-date,定义见[RFC2616],章节3.3.1

在上面的第二个链接之后,我们发现这是一个格式的例子:

Sun, 06 Nov 1994 08:49:37 GMT

并发现语法定义…

要求日期以日月年格式书写,而不是提问者使用的月日年格式。 具体来说,它对rfc1123-date的定义如下: rfc1123-date = wkday "," SP date1 SP time SP "GMT" 并像这样定义date1: date1 = 2DIGIT SP月份SP 4DIGIT ; 日、月、年(如1982年6月2日)

and

doesn't permit UTC as a timezone. The spec contains the following statement about what timezone offsets are acceptable in this format: All HTTP date/time stamps MUST be represented in Greenwich Mean Time (GMT), without exception. What's more if we dig deeper into the original spec of this datetime format, we find that in its initial spec in https://www.rfc-editor.org/rfc/rfc822, the Syntax section lists "UT" (meaning "universal time") as a possible value, but does not list not UTC (Coordinated Universal Time) as valid. As far as I know, using "UTC" in this date format has never been valid; it wasn't a valid value when the format was first specified in 1982, and the HTTP spec has adopted a strictly more restrictive version of the format by banning the use of all "zone" values other than "GMT".

如果这里的提问者使用了Expires属性,那么:

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

那样的话,它大概会起作用。


使用 信息= 1 而不是“过期”。它更短,对语法不那么挑剔,而且Max-Age优先于Expires。