HTML5 Web Storage 和 Cookie

最后更新:
阅读次数:

开门见山,先来总结一下 Cookie, LocalStorageSessionStorage 的异同,精华都在这儿呢!

总结异同

  • 相同点

    • 三者都是键值对的集合
    • 三者都会在浏览器端保存,数据存储有大小限制,同源策略限制
  • 不同点

    • 主要用途不同: cookie 主要用于标识用户身份,而 Web Storage 主要用于浏览器端存储数据
    • 操作频率不同: 一般情况下浏览器端不会修改 cookie,但会频繁操作 Web Storage
    • 存储容量不同: cookie 最大允许存储 4KB,而 Web Storage 每一个源支持 5MB(这个视浏览器而定,最小保守是 5MB,并且各浏览器支持的 localStorage 和 sessionStorage 容量上限不同。)
    • 是否添加到 HTTP 请求: cookie 每次都会包含在 http 请求中,而 Web Storage 由脚本控制选择性提交
    • 有效期不同: cookie 在设置的有效期内都有效,sessionStorage 在当前页面关闭前有效,localStorage 长期有效,直到 用户删除它或通过脚本删除它
    • 不同页面是否允许共享: sessionStorage 不能共享,localStorage 在同源文档之间共享, cookie 在同源且符合 path 规则的文档之间共享
    • 是否拥有专用 API: Web API 中没有专门操作 cookie 的 API,localStorage 和 sessionStorage 共用一套 API(Storage 对象的 API)

基本概念

  • Cookie 是一种存储在用户电脑上的用来记录一些有状态性的信息的小数据。
    • 记录购物车中添加的商品 ID
    • 记录用户上网习惯,比如最近浏览了哪些页面
    • 记录用户的身份验证信息(比如账号密码)

An HTTP cookie wiki (also called web cookie, Internet cookie, browser cookie or simply cookie) is a small piece of data sent from a website and stored on the user’s computer by the user’s web browser while the user is browsing.

  • cookie 的缺陷
    • Cookie 会被附加在每个 HTTP 请求中,所以无形中增加了流量。
    • 由于在 HTTP 请求中的 Cookie 是明文传递的,所以安全性成问题。(除非用 HTTPS)
    • Cookie 的大小限制在 4KB 左右。对于复杂的存储需求来说是不够用的。

基本用法

  • document.cookie:获取或设置与当前文档相关联的 cookie。

  • 使用 navigator.cookieEnabled 检测当前页面是否启用了 cookie

if (!navigator.cookieEnabled) {
alert("Please enable cookie~");
}
  • 一个 cookie 是一个键值对形式的字符串(name=value)
// 添加一个 cookie
document.cookie = "author=percy";

cookie 的值的字符串不允许包含任何逗号、分号或空格,所以可以用 encodeURIComponent() 来保证它不包含任何逗号、分号或空格。

let value = "hello;w,orld;";
document.cookie = "greet=" + encodeURIComponent(value);
  • 还可以为 cookie 添加一些以下的可选属性
// 设置 cookie 所在的路径
var path = '/';

// 设置 cookie 所在的域名
var domain = 'blog.percymong.com';

// 设置有效期,单位为秒,60*30 就是半小时有效,60*60*24*365 就是一年有效
// 将 max-age 的值设为 0 或负数时,会立即删除 cookie
// 参看: https://tools.ietf.org/html/rfc6265#section-5.2.2
var max-age = 60*30;

// 设置 cookie 的过期时间,这个值得格式是一个 UTC-time 字符串
var expires = (new Date()).toUTCString();

document.cookie = 'author=percy' +
';path=' + path + // 设置路径
';domain=' + domain + // 设置域名
';max-age=' + max-age + // 设置过期时间(语法更简洁)
';expires=' + expires + // 设置过期时间(兼容老式浏览器很好)
';secure'; // cookie只通过 https 协议传输

如果为一个 cookie 同时设置了 max-age 和 expires ,max-age 有更高的优先权来控制 cookie。 参看:https://tools.ietf.org/html/rfc6265#section-4.1.2

  • 使用 document.cookie 一次只能写入或更新或删除一个 cookie
// 假设现在 document.cookie 是一个空字符串

// 写入
document.cookie = "name=p";
document.cookie = "age=21";
document.cookie; // "name=p; age=21"

// 更新
document.cookie = "name=percy";
document.cookie; // "age=21; name=percy"

// 删除(删除的原理就是给当前 cookie 设置一个过期时间)
document.cookie = "age=;max-age=-1";
document.cookie; // "name=percy"

推荐使用 max-age 来设置 cookie 的过期时间,因为 max-age 比 expires 更简洁

cookie 的作用域是通过文档源和文档路径来确定的,也可通过 cookie 的 path 和 domain 属性来配置不同的作用域。

当前页面: http://blog.percymong.com/2016/12/23/npm-summary/index.html

当前页面下,cookie 默认的 domain 和 path 如下:
domain: 'blog.percymong.com'
path: '/2016/12/23/npm-summary/'

通过修改 domain,可以满足一些特殊的业务需要:比如我现在需要在 blog.percymong.com 页面访问 www.percymong.com 页面下的 cookie

StackOverflow : How do browser cookie domains work?

注意,这里的 domain 是 '.percymong.com'
document.cookie = 'author=percy;domain=.percymong.com';

cookie 有 path 概念,子路径可以访问父路径 cookie,父路径不能访问子路径 cookie。

当前页面: http://www.example.com/tag/index.html

假设在当前页面下设置了一个 cookie

该 cookie 对下面的页面是可见的:
http://www.example.com/tag/demo.html
http://www.example.com/tag/javascript/index.html
http://www.example.com/tag/css/test/demo.html

该 cookie 对下面的页面是不可见的:
http://www.example.com
http://www.example.com/index.html
http://www.example.com/test/demo.html

(2017/7/8)这几天做项目时,由于要清除本地 cookie,但发现半天都清理不掉,不科学啊,过期时间我都设置成过去的时间了啊。半天时间后,在 Stack Overflow 上看到了相同的问题,经高手这么一指点,瞬间通了。原来我忘记了 cookie 也是有作用域的,只有设置了相同的 domain 和 path 的 cookie 才可以被删除。

清除 cookie 时一定要注意 cookie 的作用域哦

有时候,cookie 直接由后端进行删除,前端都省得删了。

点击退出登录  
-> ajax 发送用户登出数据
-> 后台返回过期 cookie
-> 过期 cookie 覆盖之前的 cookie
-> cookie 失效,登出完成

不同于 localStorage 和 sessionStorage,Web API 中没有专门用于操作 cookie 的 API,所以网上找到了别人写的一个库,专门操作 cookie。

库名:js.cookie.js,a simple, lightweight JavaScript API for handling browser cookies.

Web 存储(Web Storage)

Web Storage 包含两种机制:localStoragesessionStorage

  • window.localStorage:返回一个 Storage 对象

    • 存储在 localStorage 里面的数据没有过期时间,长期有效,直到用户主动删除它或通过脚本删除它
    • localStorage 的作用域仅限定在同源。
  • window.sessionStorage:也返回一个 Storage 对象

    • 存储在 sessionStorage 里面的数据在页面会话结束时(关闭当前页面或关闭浏览器)会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会保持原来的页面会话。
    • 复制后的标签页不会保持原来的会话,但是会复制原页面的 sessionStorage 数据。(Chrome 亲测)
    • sessionStorage 的作用域不仅限定在同源,还限定在相同会话窗口中。

localStorage 和 sessionStorage 共用一套操作 API:Storage 对象 API

  • Storage 对象 API

    • Storage.length:返回存储的数据项数量
    • Storage.key(keyIndex):取得对应索引的键名
    • Storage.getItem(keyName):取得对应键名的值
    • Storage.setItem(keyName,keyValue):增加或更新一个数据项
    • Storage.removeItem(keyName):删除对应键名的数据项
    • Storage.clear():清空所有存储的数据项
  • storage 事件

对 Storage 对象进行任何修改,都会触发 storage 事件。

自己可以做个测试,打开同源的两个页面,一个页面修改 localStorage 数据,一个页面监听 storage 事件。

window.onstorage = function(e){
console.log('key : ' + e.key); // 发生变化的键名
console.log('oldValue : ' + e.oldValue); // 旧值
console.log('newValue : ' + e.newValue); // 新值
};

测试 sessionStorage 时,会有点小麻烦,看下面解释。

The sessionStorage is isolated for each tab, so they can not communicate. Events for sessionStorage are triggered only in between frames on the same tab.

参考资料