客户端数据存储----Cookie From 《高程3》

媒介

本篇重要引见Cookie手艺的念书总结,然则我以为逻辑上最好会和Web Storage手艺放在一同举行对照,因而后续会再总结一篇关于WEB存储的姊妹总结,敬请期待。

起首先来一段总结:Cookie用于当地数据存储,涌现在服务器和浏览器交互的响应Set-Cookie头部和请求Cookie头部中,遭到单域名下Cookie的数量、单个Cookie大小、机能、平安限定。子Cookie手艺的涌现缓解了单域名下Cookie的数量限定,关于子Cookie有一整套东西函数能够运用。

HTTP Cookie 简介

用户的信息最好存储在客户端上,这就对客户端数据存储提出了请求。最早的处置惩罚体式格局就是Cookie。HTTP Cookie,一般直接叫做 cookie,最初是在客户端用于存储会话信息的。该规范请求服务器对恣意 HTTP 请求发送 Set-Cookie HTTP 头作为响应的一部份,个中包括会话信息。

一个典范的响应头部:

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value

这个 HTTP 响应设置以 name 为称号、以 value 为值的一个 cookie,称号和值在传送时都必须是URL 编码的。浏览器会存储如许的会话信息,并在这以后,经由过程为每一个请求增加 Cookie 头将信息发送回服务器:

GET /index.html HTTP/1.1
Cookie: name=value
Other-header: other-header-value

Cookie的接见、数量和大小限定

cookie 在性子上是绑定在特定的域名下的。当设定了一个 cookie 后,再给建立它的域名发送请求时,都邑包括这个 cookie。这个限定确保了储存在 cookie 中的信息只能让同意的接受者接见,而没法被其他域接见。

由于 cookie 是存在客户端盘算机上的,还到场了一些限定确保 cookie 不会被歹意运用,同时不会占有太多磁盘空间。每一个域的 cookie 总数是有限的,不过浏览器之间各有不同:
1)IE6 以及更低版本限定每一个域名最多 20 个 cookie。
2)IE7 和以后版本每一个域名最多 50 个。 IE7 最初是支撑每一个域名最大 20 个 cookie,以后被微软的一个补丁所更新。
3)Firefox 限定每一个域最多 50 个 cookie。
4)Opera 限定每一个域最多 30 个 cookie。
5)Safari 和 Chrome 关于每一个域的 cookie 数量限定没有硬性规定。

当凌驾单个域名限定以后还要再设置 cookie,浏览器就会消灭之前设置的 cookie。 IE 和 Opera 会删除近来起码运用过的(LRU, Least Recently Used) cookie,腾出空间给新设置的 cookie。 Firefox 看上去好像是随机决定要消灭哪一个 cookie,所以斟酌 cookie 限定异常重要,以防止涌现不可预期的效果。

浏览器中关于 cookie 的尺寸也有限定。大多数浏览器都有约莫 4096B(加减 1)的长度限定。为了最好的浏览器兼容性,最好将悉数 cookie 长度限定在 4095B(含 4095)之内。尺寸限定影响到一个域下一切的 cookie,而并不是每一个 cookie 零丁限定。假如你尝试建立凌驾最大尺寸限定的 cookie,那末该 cookie 会被悄无声息地丢掉。

cookie 的组成

1)称号:一个唯一肯定 cookie 的称号。cookie 称号是不辨别大小写的。cookie 的称号必须是经由 URL 编码的。
2)值:储存在 cookie 中的字符串值。值必须被 URL 编码。
3)域: cookie 关于哪一个域是有用的。一切向该域发送的请求中都邑包括这个 cookie 信息。
4)途径:关于指定域中的谁人途径,应当向服务器发送 cookie。
5)失效时刻:示意 cookie 什么时刻应当被删除的时刻戳(也就是,什么时刻应当住手向服务器发送这个cookie)。默许状况下,浏览器会话完毕时行将一切 cookie 删除;不过也能够自身设置删除时刻。这个值是个 GMT 花样的日期(Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定应当删除cookie 的准确时刻。因而, cookie 可在浏览器封闭后照旧保留在用户的机械上。假如你设置的失效日期是个之前的时刻,则 cookie 会被马上删除。
6)平安标志:指定后, cookie 只要在运用 SSL 衔接的时刻才发送到服务器。比方, cookie 信息只能发送给 https://www.wrox.com,而 http://www.wrox.com 的请求则不能发送 cookie。

每一段信息都作为 Set-Cookie 头的一部份,运用分号加空格分开每一段。secure 标志是 cookie 中唯一一个非名值对儿的部份,直接包括一个 secure 单词。特别要注意,域、途径、失效时刻和 secure 标志都是服务器给浏览器的指导(是从服务器发还的响应),以指定什么时刻应当发送 cookie。这些参数并不会作为发送到服务器的 cookie 信息的一部份,只要名值对儿才会被发送到服务器。

设置 cookie 的花样以下,和 Set-Cookie 头中运用的花样一样,以下:
name=value; expires=expiration_time; path=domain_path;
domain=domain_name; secure

建立、删除和接见Cookie的东西函数

由于 JavaScript 中读写 cookie 不是异常直观,经常须要写一些函数来简化 cookie 的功用。基础的cookie 操纵有三种:读取、写入和删除。建立cookie的东西函数:

    var CookieUtil = {
    get: function (name) {
    var cookieName = encodeURIComponent(name) + '=',
    cookieStart = document.cookie.indexOf(cookieName),
    cookieValue = null;
    if (cookieStart > - 1) {
      var cookieEnd = document.cookie.indexOf(';', cookieStart);
      if (cookieEnd == - 1) {
        cookieEnd = document.cookie.length;
      }
      cookieValue = decodeURIComponent(document.cookie.substring(cookieStart
      + cookieName.length, cookieEnd));
    }
    return cookieValue;
  },
  set: function (name, value, expires, path, domain, secure) {
    var cookieText = encodeURIComponent(name) + '=' +
    encodeURIComponent(value);
    if (expires instanceof Date) {
      cookieText += '; expires=' + expires.toGMTString();
    }
    if (path) {
      cookieText += '; path=' + path;
    }
    if (domain) {
      cookieText += '; domain=' + domain;
    }
    if (secure) { //secure在这里是布尔值
      cookieText += '; secure';
    }
    document.cookie = cookieText;
  },
  unset: function (name, path, domain, secure) {
    this.set(name, '', new Date(0), path, domain, secure);
  }

};

CookieUtil.get()要领依据 cookie 的名字猎取响应的值。它会在 document.cookie 字符串中查找 cookie 名加上等于号的位置。假如找到了,那末运用 indexOf()查找该位置以后的第一个分号(示意了该 cookie 的完毕位置)。假如没有找到分号,则示意该 cookie 是字符串中的末了一个,则余下的字符串都是 cookie 的值。该值运用 decodeURIComponent()举行解码并末了返回。假如没有发明 cookie,则返回 null。
CookieUtil.set()要领在页面上设置一个 cookie,吸收以下几个参数: cookie 的称号, cookie 的值,可选的用于指定 cookie 什么时刻应被删除的 Date 对象, cookie 的可选的 URL 途径,可选的域,以及可选的示意是不是要增加 secure 标志的布尔值。参数是根据它们的运用频次分列的,只要头两个是必须的。在这个要领中,称号和值都运用encodeURIComponent()举行了URL编码,并搜检其他选项。假如expires参数是 Date 对象,那末会运用 Date 对象的 toGMTString()要领准确花样化 Date 对象,并增加到expires 选项上。要领的其他部份就是组织 cookie 字符串并将其设置到 document.cookie 中。
没有删除已有 cookie 的直接要领。所以,须要运用雷同的途径、域和平安选项再次设置 cookie,并将失效时刻设置为过去的时刻。 CookieUtil.unset()要领能够处置惩罚这类事变。它吸收 4 个参数:要删除的 cookie 的称号、可选的途径参数、可选的域参数和可选的平安参数。这些参数加上空字符串并设置失效时刻为 1970 年 1 月 1 日(初始化为 0ms 的 Date 对象的值),传给 CookieUtil.set()。如许就可以确保删除 cookie。

FireBug测试效果

FireBug对应哪一个页面,设置的cookie就存储在谁人页面对应的域。翻开当地apache服务器的/localhost/alien/页面,在个中翻开firebug。
测试实例1:

    CookieUtil.set("name", "Nicholas");
    CookieUtil.set("book", "Professional JavaScript");
    //读取 cookie 的值
    console.log(CookieUtil.get("name")); //"Nicholas"
    console.log(CookieUtil.get("book")); //"Professional JavaScript"

《客户端数据存储----Cookie From 《高程3》》

测试实例2 删除cookie:
CookieUtil.unset(“name”);
CookieUtil.unset(“book”);
此时FireBug中不显现任何Cookie。

测试实例3 翻开当地服务器localhost主页,设置平安的cookie。
CookieUtil.set(“name”,”Nicholas”, null, null, null, true);
console.log(CookieUtil.get(“name”));
设置secure为true时,前面缺乏的参数都定义为null。这是由于JavaScript会根据递次对应参数。
《客户端数据存储----Cookie From 《高程3》》
测试效果:平安项显现“平安”。

子Cookie

子Cookie的目标是为了打破单域名下的Cookie数量限定,也就是在一个Cookie中存储多个名值对,罕见花样以下:
name=name1=value1&name2=value2&name3=value3&name4=value4&name5=value5

关于子Cookie的设置、猎取和删除有以下东西函数:

var SubCookieUtil = {
  get: function (name, subName) {
    var subCookies = this.getAll(name);
    if (subCookies) {
      return subCookies[subName];
    } else {
      return null;
    }
  },
  getAll: function (name) {
    var cookieName = encodeURIComponent(name) + '=',
    cookieStart = document.cookie.indexOf(cookieName),
    cookieValue = null,
    cookieEnd,
    subCookies,
    i,
    parts,
    result = {
    };
    if (cookieStart > - 1) {
      cookieEnd = document.cookie.indexOf(';', cookieStart);
      if (cookieEnd == - 1) {
        cookieEnd = document.cookie.length;
      }
      cookieValue = document.cookie.substring(cookieStart +
      cookieName.length, cookieEnd);
      if (cookieValue.length > 0) {
        subCookies = cookieValue.split('&');
        for (i = 0, len = subCookies.length; i < len; i++) {
          parts = subCookies[i].split('=');
          result[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
        }
        return result;
      }
    }
    return null;
  },
  set: function (name, subName, value, expires, path, domain, secure) {
    var subcookies = this.getAll(name) || {
    };
    subcookies[subName] = value;
    this.setAll(name, subcookies, expires, path, domain, secure);
  },
  setAll: function (name, subcookies, expires, path, domain, secure) {
    var cookieText = encodeURIComponent(name) + '=',
    subcookieParts = new Array(),
    subName;
    for (subName in subcookies) {
      //由于采纳push要领,新的子Cookie被延续到本来的Cookie中
      if (subName.length > 0 && subcookies.hasOwnProperty(subName)) {
        subcookieParts.push(encodeURIComponent(subName) + '=' +
        encodeURIComponent(subcookies[subName]));
      }
    }
    if (subcookieParts.length > 0) {
      cookieText += subcookieParts.join('&');
      if (expires instanceof Date) {
        cookieText += '; expires=' + expires.toGMTString();
      }
      if (path) {
        cookieText += '; path=' + path;
      }
      if (domain) {
        cookieText += '; domain=' + domain;
      }
      if (secure) {
        cookieText += '; secure';
      }
    } else {
      cookieText += '; expires=' + (new Date(0)).toGMTString();
    }
    document.cookie = cookieText;
  },
  unset: function (name, subName, path, domain, secure) {
    var subcookies = this.getAll(name);
    if (subcookies) {
      delete subcookies[subName];
      this.setAll(name, subcookies, null, path, domain, secure);
    }
  },
  unsetAll: function (name, path, domain, secure) {
    this.setAll(name, null, new Date(0), path, domain, secure);
  }
};

以下是对上述要领的剖析:
猎取子 cookie 的要领有两个: get()和 getAll()。个中 get()猎取单个子 cookie 的值, getAll()猎取一切子 cookie 并将它们放入一个对象中返回,对象的属性为子 cookie 的称号,对应值为子 cookie对应的值。 get()要领吸收两个参数: cookie 的名字和子 cookie 的名字。它实在就是挪用 getAll()猎取一切的子 cookie,然后只返回所需的那一个(假如 cookie 不存在则返回 null)。

SubCookieUtil.getAll()要领和 CookieUtil.get()在剖析 cookie 值的体式格局上异常类似。区分在于 cookie 的值并不是马上解码,而是先依据&字符将子 cookie 支解出来放在一个数组中,每一个子 cookie再依据等于号支解,如许在 parts 数组中的前一部份就是子 cookie 名,后一部份则是子 cookie 的值。这两个项目都要运用 decodeURIComponent()来解码,然后放入 result 对象中,末了作为要领的返回值。假如 cookie 不存在,则返回 null。

set()要领吸收 7 个参数: cookie 称号、子 cookie 称号、子 cookie 值、可选的 cookie 失效日期或时刻的 Date 对象、可选的 cookie 途径、可选的 cookie 域和可选的布尔 secure 标志。一切的可选参数都是作用于 cookie自身而非子 cookie。为了在同一个 cookie中存储多个子 cookie,途径、域和 secure标志必须一致;针对悉数 cookie 的失效日期则能够在任何一个零丁的子 cookie 写入的时刻同时设置。在这个要领中,第一步是猎取指定 cookie 称号对应的一切子 cookie。逻辑或操纵符“ ||”用于当 getAll()返回 null 时将 subcookies 设置为一个新对象。然后,在 subcookies 对象上设置好子 cookie 值并传给setAll()。

setAll()要领吸收 6 个参数: cookie 称号、包括一切子 cookie 的对象以及和 set()中一样的 4个可选参数。这个要领运用 for-in 轮回遍历第二个参数中的属性。为了确保确实是要保留的数据,运用了 hasOwnProperty()要领,来确保只要实例属性被序列化到子 cookie 中。由于可能会存在属性名为空字符串的状况,所以在把属性名到场效果对象之前还要搜检一下属性名的长度。将每一个子 cookie的名值对儿都存入 subcookieParts 数组中,以便稍后能够运用 join()要领以&号组合起来。

一般 cookie 能够经由过程将失效时刻设置为过去的时刻的要领来删除,然则子 cookie 不能如许做。为了删除一个子 cookie,起首必须猎取包括在某个 cookie中的一切子 cookie,然后仅删除须要删除的谁人子 cookie,然后再将余下的子 cookie 的值保留为 cookie的值。unset()要领用于删除某个 cookie 中的单个子 cookie而不影响其他的;而 unsetAll()要领则等同于 CookieUtil.unset(),用于删除悉数 cookie。和 set()及 setAll()一样,途径、域和 secure 标志必须和之前建立的 cookie 包括的内容一致。

firebug测试实例

//设置两个 cookie
SubCookieUtil.set(“data”, “name”, “Nicholas”);
SubCookieUtil.set(“data”, “book”, “Professional JavaScript”);
《客户端数据存储----Cookie From 《高程3》》

//设置悉数子 cookie 和失效日期
SubCookieUtil.setAll(“data”, { name: “Nicholas”, book: “Professional JavaScript” },new Date(“January 1, 2018”));
《客户端数据存储----Cookie From 《高程3》》

//修正名字的值,并修正 cookie 的失效日期
SubCookieUtil.set(“data”, “name”, “Michael”, new Date(“February 1, 2010”));
《客户端数据存储----Cookie From 《高程3》》

//删除一切子Cookie
SubCookieUtil.unsetAll(‘data’);

Cookie的限定

1)单域名下数量限定和大小限定:子Cookie只是打破了单个域名下Cookie数量限定,然则Cookie的大小照旧受限,因而要注意子Cookie的大小不能使单个Cookie超越大小限定。
2)机能限定:由于一切的 cookie 都邑由浏览器作为请求头发送,所以在 cookie 中存储大批信息会影响到特定域的请求机能。 cookie 信息越大,完成对服务器请求的时刻也就越长。只管浏览器对 cookie 举行了大小限定,不过最好照样尽可能在 cookie 中少存储信息,以防止影响机能。
3)平安限定:cookie 数据并不是存储在一个平安环境中,个中包括的任何数据都能够被别人接见。所以不要在 cookie 中存储诸如信用卡号或许个人地点之类的数据。
cookie 的性子和它的范围使得其并不能作为存储大批信息的抱负手腕,所以又涌现了其他要领。

    原文作者:zhangding
    原文地址: https://segmentfault.com/a/1190000007199753
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞