我有两个问题。我明白,如果我在cookie中指定域名为。example.com(带前导点),那么所有子域都可以共享一个cookie。
subdomain.example.com可以访问在example.com中创建的cookie(没有www子域)吗?
example.com(没有www子域)可以访问在subdomain.example.com中创建的cookie吗?
我有两个问题。我明白,如果我在cookie中指定域名为。example.com(带前导点),那么所有子域都可以共享一个cookie。
subdomain.example.com可以访问在example.com中创建的cookie(没有www子域)吗?
example.com(没有www子域)可以访问在subdomain.example.com中创建的cookie吗?
如果你像这样设置cookie:
Set-Cookie: name=value
然后cookie将只应用于请求域,并且只会被发送到完全相同的域,而不是任何其他子域。(参见什么是主机专用cookie?)
两个不同的域(例如example.com和subdomain.example.com,或sub1.example.com和sub2.example.com)只有在域名属性出现在头部时才能共享cookie:
Set-Cookie: name=value; domain=example.com
域属性必须“domain-match”请求URL才能有效,这基本上意味着它必须是请求域或超级域。所以这适用于问题中的两个例子,也适用于两个独立子域之间的共享。
然后,该cookie将被发送给example.com的任何子域,包括嵌套的子域,如subsub.subdomain.example.com。(请记住,还有其他属性可能会限制cookie的范围和由浏览器发送的时间,如path或Secure)。
由于域名匹配的工作方式,如果您希望sub1.example.com和sub2.example.com共享cookie,那么您还将与sub3.example.com共享它们。
参见:
WWW vs no-www和cookie Setcookie.net:一个你可以尝试的网站(免责声明:由我开发,针对这个问题)
关于域属性中前导点的注意事项:在早期的RFC 2109中,只有带有前导点的域(domain=.example.com)才能跨子域使用。但是这不能与顶级域共享,所以您所要求的在旧规范中是不可能的。
但是,新的规范RFC 6265忽略了任何前导点,这意味着您可以在子域以及顶级域上使用cookie。
我不确定cmbuckley的回答是全面的。我读到的是:
除非cookie的属性另有指示,否则cookie就是 只返回到源服务器(而不是,例如,任何 子域),并且在当前会话结束时过期(如 由用户代理定义)。用户代理忽略未识别的cookie。 RFC 6265
Also
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提供的令人敬畏的饼干测试网站,对于那些像我一样错过了他的答案的人;值得往上翻。
饼干测试
在这两种情况下,是的,它可以,这是Internet Explorer和Edge的默认行为。
其他答案增加了有价值的见解,但它们主要描述了Chrome的行为。需要注意的是,这种行为在ie中是完全不同的。CMBuckley的非常有用的测试脚本演示了在Chrome中,当没有指定域时,cookie不会在根域和子域之间共享。
但是,在Internet Explorer中进行的相同测试显示它们是共享的。这个ie案例更接近CMBuckley的www-or-not-www链接中的详细描述。我知道这是事实,因为我们的系统在根域和子域上都使用了不同的服务堆栈cookie。这一切都很正常,直到有人在Internet Explorer中访问它,两个系统为谁的会话cookie将获胜而争吵,直到我们炸毁了缓存。
下面是一个使用DOM cookie API的示例,因此我们可以自己查看行为。
如果我们执行以下JavaScript代码,
文件。cookie =“键=值”
它看起来和执行是一样的:
文档。Cookie = "key=value;domain=example.com"
cookie密钥(仅)在域名example.com上可用。
现在,如果您在example.com上执行以下JavaScript代码,
文档。Cookie = "key=value;domain=。example.com"
cookie密钥将对example.com和subdomain.example.com可用。
最后,如果您尝试在subdomain.example.com上执行以下命令,
文档。Cookie = "key=value;domain=。example.com"
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
Why?
根据RFC 6265章节5.3.6存储模型,
如果规范化的request-host与domain-attribute不匹配:完全忽略cookie并中止这些步骤。
和RFC 6265章节5.1.3域匹配,
Domain Matching A string domain-matches a given domain string if at least one of the following conditions hold: The domain string and the string are identical. (Note that both the domain string and the string will have been canonicalized to lower case at this point.) All of the following conditions hold: * 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
也检查一下这个答案。
如果您正在使用localhost,请小心! 如果你像这样在JavaScript中存储你的cookie:
document.cookie = "key=value;domain=localhost"
它可能无法被子域访问,比如sub.localhost。为了解决这个问题,你需要使用VirtualHost。例如,你可以用服务器名localhost.com配置你的虚拟主机,然后你就可以像这样在你的域和子域上存储你的cookie:
document.cookie = "key=value;domain=localhost.com"
我这样做,对我很有效:
Cookie.set('token', 'some jwt-token', { expire:50000, domain: 'example.com' })