在子域和域之间共享cookie

我有两个问题。我明白,如果我在cookie中指定域为.example.com(带前导点),那么所有子域都可以共享一个cookie。

subdomain.example.com可以访问在example.com中创建的cookie(没有www子域)吗?

example.com(没有www子域)可以访问在subdomain.example.com中创建的cookie吗?

502506 次浏览

如果你像这样设置cookie:

Set-Cookie: name=value

那么cookie将只应用于请求域,并且只会发送请求到完全相同的域,而不是任何其他子域。(见# EYZ1)

两个不同的域(例如example.comsubdomain.example.com,或sub1.example.comsub2.example.com)只能在头文件中出现domain属性时共享cookie:

Set-Cookie: name=value; domain=example.com

域属性必须"domain-match"请求URL是有效的,这基本上意味着它必须是请求域或超级域。所以这适用于问题中的两个例子,也适用于两个独立子域之间的共享。

然后这个cookie将被发送到example.com的任意子域,包括嵌套的子域,如subsub.subdomain.example.com。(请记住,还有其他属性可以限制cookie的范围和由浏览器发送的时间,如pathSecure)。

由于域匹配的工作方式,如果您希望sub1.example.comsub2.example.com共享cookie,那么您还将与sub3.example.com共享它们。

参见:


关于domain属性中前导点的注意事项:在早期的RFC 2109中,只有带有前导点(domain=.example.com)的域可以跨子域使用。但是这不能与顶级域共享,所以您所要求的在旧规范中是不可能的。

但是,新的规范RFC 6265忽略了任何前导点,这意味着您可以在子域以及顶级域上使用cookie。

简单的解决方案

setcookie("NAME", "VALUE", time()+3600, '/', EXAMPLE.COM);

Setcookie的第5个参数决定了cookie可用的(子)域。将它设置为(EXAMPLE.COM)使它可用于任何子域(例如:SUBDOMAIN.EXAMPLE.COM)

参考:# EYZ0

我不确定@cmbuckley的回答是否全面。我读到的是:

除非cookie的属性另有指示,否则cookie是 只返回到源服务器(而不是,例如,任何 子域),并且在当前会话结束时过期(如 由用户代理定义)。

.用户代理忽略未识别的cookie

RFC 6265

8.6.  Weak Integrity


Cookies do not provide integrity guarantees for sibling domains (and
their subdomains).  For example, consider foo.example.com and
bar.example.com.  The foo.example.com server can set a cookie with a
Domain attribute of "example.com" (possibly overwriting an existing
"example.com" cookie set by bar.example.com), and the user agent will
include that cookie in HTTP requests to bar.example.com.  In the
worst case, bar.example.com will be unable to distinguish this cookie
from a cookie it set itself.  The foo.example.com server might be
able to leverage this ability to mount an attack against
bar.example.com.

对我来说,这意味着你可以保护cookie不被子域/域读取,但不能阻止将cookie写入其他域。因此,有人可能会通过控制同一浏览器访问的另一个子域来重写您的网站cookie。这可能不是一个大问题。

很棒的饼干测试网站由@cmbuckley提供/那些像我一样在他的回答中错过了它的人;值得向上滚动和向上投票/:

在这两种情况下,是的,它可以,这是IE和Edge的默认行为。

其他答案增加了有价值的见解,但主要描述了Chrome的行为。需要注意的是,在IE中这种行为是完全不同的。CMBuckley的非常有用的测试脚本演示了在Chrome中,当没有指定域时,cookie不会在根域和子域之间共享。然而,在IE中同样的测试显示它们是共享的。IE案例更接近CMBuckley的www-or-not-www链接中的详细描述。我知道这是事实,因为我们的系统在根域和子域上都使用了不同的服务堆栈cookie。这一切都很正常,直到有人在IE中访问它,两个系统为谁的会话cookie将赢得比赛,直到我们炸毁了缓存。

下面是一个使用DOM cookie API (https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie)的示例,因此我们可以自己看到行为。

如果我们执行以下JavaScript:

# EYZ0

它看起来和执行是一样的:

# EYZ0

cookie 关键(仅)在域example.com上可用。


现在,如果你在example.com上执行以下JavaScript:

文档。Cookie = "key=value;domain=.example.com"

关键 cookie对example.comsubdomain.example.com可用。


最后,如果你尝试在subdomain.example.com上执行以下命令:

# EYZ0

cookie 关键subdomain.example.com可用吗?我有点惊讶,这是允许的;我假定子域能够在父域上设置cookie会违反安全。

请大家注意,你可以在一个域上设置一个子域的cookie。

(在请求subdomain.example.com的响应中发送)

Set-Cookie: name=value; Domain=example.com // GOOD

但是你不能在子域上设置了一个域的cookie。

(在请求example.com的响应中发送)

Set-Cookie: name=value; Domain=subdomain.example.com // Browser rejects cookie

为什么?

根据RFC 6265章节5.3.6存储模型规格

如果规范化的请求主机没有domain-match域属性:完全忽略cookie并中止这些步骤。

和# EYZ0

域匹配

字符串domain-match给定的域字符串,如果至少满足以下条件之一:

  1. 域字符串与字符串相同。(请注意 域字符串和字符串将被规范化

  2. 以下所有条件都成立:

  *  The domain string is a suffix of the string.


*  The last character of the string that is not included in the
domain string is a %x2E (".") character.


*  The string is a host name (i.e., not an IP address).

因此,subdomain.example.com域匹配example.com,但example.com不匹配subdomain.example.com

也检查这个答案

如果你在本地主机上工作,请小心! 如果你像这样在JavaScript中存储cookie:

document.cookie = "key=value;domain=localhost"

您的子域可能无法访问它,比如sub.localhost。为了解决这个问题,你需要使用VirtualHost。例如,你可以配置你的虚拟主机ServerName localhost.com,然后你就可以像这样在你的域和子域上存储你的cookie:

document.cookie = "key=value;domain=localhost.com"

我这样做,对我很有效:

Cookie.set('token', 'some jwt-token', { expire:50000, domain: 'example.com' })