每个网页请求都会发送浏览器的cookie吗?

264

每个网络请求都会发送浏览器的Cookies吗?

我指的是图片、.js文件等的请求,而不是页面访问。

更新 如果一个网页有50个元素,那就是50个请求。为什么它会为每个请求发送相同的cookie(s),难道它不会缓存或者已经知道了吗?


13
在这种情况下,我认为无法进行缓存 -- 我们正在讨论浏览器向服务器发送数据,而不是反过来。你无法确定在用户发送一个请求之后服务器是否“已经拥有它”,原因很多。可能有大量不相互通信的服务器;服务器可能不想(或没有空间)记住有关之前请求的任何信息 -- HTTP 应该是无状态的;每个请求都应该是独立的。因此,像身份验证凭据一样,cookie 必须随每个请求一起发送。 - Ian Clelland
我在我的回答更新中提到了为什么对于cookies来说缓存没有意义:https://dev59.com/rXM_5IYBdhLWcg3wiDuA#1336178 - igorsantos07
8个回答

274

是的,只要所请求的URL在cookie中定义的相同域和路径内(并且所有其他限制条件 -- 安全、httponly、未过期等)保持不变,那么cookie将被发送给每个请求。


136
顺便说一下,这就是为什么页面速度工具(如Google Page Speed或Yahoo的YSlow)建议从单独的、无cookie的域名提供静态内容的原因。 - ceejayoz
我在我的更新答案中提到了从单独的域名提供内容的问题:https://dev59.com/rXM_5IYBdhLWcg3wiDuA#1336178 - igorsantos07
浏览器在从Site1重定向到Site2时是否会发送Site2 Cookies? - Zeigeist

117

正如其他人所说,如果cookie的主机、路径等限制得到满足,它将被发送50次。

但你也问了为什么:因为cookie是HTTP的一个特性,而HTTP是无状态的。HTTP被设计成在请求之间不存储任何状态就可以工作。

事实上,服务器没有确定识别哪个用户发送了给定请求的明确方式; 在单个Web代理(因此IP地址)后面可能有数千个用户。 如果每个请求不发送cookie,服务器将无法知道请求某个资源的是哪个用户。

最后,浏览器无法确定服务器是否需要这些cookie,它只知道服务器指示它在发送到foo.com的任何请求中发送cookie。 有时图像需要它们(例如针对每个用户动态生成),有时不需要,但浏览器无法判断。


1
HTTP 1.1 是一种多路复用的方案,这是真的吗?即请求被捆绑在单个 TCP 连接中。当然,每个请求都会附带一个 cookie 的副本。但是如果问题是大量的传输重复,HTTP 1.1 可以进行优化。不过我不知道它是否实际上这样做了... - Chris Noe
1
那么问题就变成了“浏览器打算将cookie附加到哪些请求上?”服务器使用cookie设置策略,以决定应将cookie发送回哪些域和URL路径,但然后它就忘记了。您需要一种方法来指定连接中某些请求具有cookie,而其他请求则没有。除非在每个请求中显式包含它们,否则HTTP / 1.1绝对不存在这种情况。老实说,减少带宽的更好(符合标准)解决方案是客户端gzip内容编码,但目前没有人支持它。 - Ian Clelland
1
@Ian Clelland:客户端必须发送第一条消息,因此它不知道服务器将发送什么样的Accept-Encoding(如果服务器发送该字段,则HTTP/1.1 §14.3表示其为请求头)。问题在于,即使在同一台服务器上,URL也可能会有所不同,并且随着时间的推移可能会发生变化,因此使其正常工作是非常困难的。 - derobert
1
@Chris:不,keepalive只是节省TCP连接的建立/拆除开销,仅此而已。每个请求仍然发送完整的标头。但是,管线化(发送多个请求而无需等待响应)可以大大提高效率。HTTP/1.1 §8.1 给出了详细信息。 - derobert
子域站点是否仅在每个请求中发送子域 cookie,还是其域 cookie 和其他外部域 cookie 也一并发送? - Yusuf

34

是的,每个请求都会发送属于同一域的cookie。由于HTTP是无状态的,它不会缓存cookie。这意味着每个请求必须足够让服务器知道如何处理它。例如,如果您有一些只允许特定用户访问的图像,则必须在这50个请求中的每一个请求中发送身份验证cookie,以便服务器知道这是您而不是其他人或者一个来自大量请求之间的访客。

话虽如此,由于其他限制(如HTTPS设置、路径或域),cookie可能不会被发送。尤其要注意的是:cookie不会在不同的域之间共享。这对于减少针对静态文件的HTTP调用的大小非常有帮助,比如您提到的图像和脚本。
例如:您在www.stackoverflow.com上有4个cookie;如果您请求www.stackoverflow.com/images/logo.png,所有这4个cookie将会被发送。
但是,如果您请求stackoverflow.com/images/logo.png(注意子域名的变化)或者images.stackoverflow.com/logo.png,那么这4个cookie将不会存在,但是与这些域相关的cookie可能存在。

您可以在这篇StackOverflow博客文章中了解更多关于cookie和图像请求的信息。


子域站点是否仅在每个请求中发送子域cookie,还是其域cookie和其他外部域cookie也会被发送? - Yusuf

17

不是每个请求都会发送cookies,这取决于cookie的配置和客户端与服务器的连接。

例如,如果您的cookie的“secure”选项设置为“true”,则必须通过安全的HTTPS连接传输。也就是说,当您使用HTTP协议访问该网站时,因为`secure`标志为`true`,这些cookie将不会被浏览器发送。


11

已经过去了3年

浏览器不会发送cookie的另一个原因是您可以在<script>标记中添加crossOrigin属性,将值设置为"anonymous"。这将防止将cookie发送到目标服务器。99.9%的情况下,您的JavaScript文件都是静态文件,您不会根据请求的cookie生成该JS代码。如果您有1KB的cookie,并且您的页面有200个资源,则用户上传了200KB,这可能需要一些时间在3G上,对结果页面没有任何影响。有关参考,请访问HTML属性:crossOrigin


请解释。 - Jake
5
你可以在<script>标签中添加crossOrigin属性,并将值设置为"anonymous"。这样可以防止向目标服务器发送cookie。99.9%的情况下,你的JavaScript代码都是静态文件,不会基于请求的cookie生成JS代码。如果你有1KB的cookie,并且页面上有200个资源,则用户上传了200KB,这可能需要一些时间才能在3G上完成,并对结果页面没有任何影响。请访问https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes获取参考资料。 - gilm

8

Cookie有一个“path”属性。如果“path = /”,答案是Yes。


是的,您可以组织您的网站/应用程序结构,使所有需要 cookie 的 URL 都在 /app/ 或类似位置 - 这将保持可移植性,而无需使用单独的子域来消除冗余开销。或者您可以首先放弃现在无用的 Google Analytics。我见过如此之长的 cookie 标头,以至于我怀疑我的祖母是否在编织它们。 - Jake

4
我知道这是一个旧的帖子。但我刚刚注意到,如果您在域名后面添加一个尾随点,大多数浏览器将不会为该域发送cookie。例如,http://example.com.不会接收设置为.example.com的cookie。另一方面,Apache将它们视为相同的主机。我发现这很有用,可以使外部资源使用交叉域跟踪变得更加困难,但您也可以出于性能原因使用它。请注意,这会破坏https证书的验证。我在browsershots和自己的设备上运行了几个测试。这个技巧对于除Safari(移动和桌面)之外的几乎所有浏览器都有效,后者将在请求中包含cookies。

它是如何“使包含的外部资源跨域跟踪更加困难”的?你是在谈论像Facebook Like和其他小部件吗?我们知道这些小部件会跟踪意外仍然登录的用户的浏览记录。 - Jake
是的。这会使它更加困难,因为大多数浏览器不会发送cookie。所以,如果您从google.com包含某些内容,并且您已登录到google,则google无法链接这两个请求。虽然这并不是保证,但有些浏览器仍会发送cookie,并且还有一些不太可靠和不常用的方法来识别用户(如IP地址),这些方法仍将起作用。最大的缺点是,您无法使用HTTPS,这在今天有点无用。 - Gellweiler

3

简短的回答是:是的。以下内容摘自JS文档

曾经使用Cookies来进行一般客户端存储。虽然当它们是在客户端上唯一的数据存储方式时,这种做法是合法的,但现在建议使用现代化的存储API。由于Cookie会随着每个请求一起发送,因此它们可能会恶化性能(特别是对于移动数据连接)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接