cookie、localStorage、sessionStroage介绍及其对比

1. cookie

cookie最初是设计给服务端用的。若是客户端有cookie,则每次请求都会发给服务端。下面来具体看一下这个机制。node

1.1 cookie 的设置

就像上面说的,cookie最初是设计给服务端使用的。cookie就像服务端给这个客户端加的一个标签,当客户端再次请求时,会带着这个标签,那么服务器就能经过携带的cookie知道当前的客户端是谁了。api

cookie的设置过程大致以下:跨域

  1. 客户端请求服务端,服务端看到客户端是新来的,就用回复头里的set-cookie设置一个cookie给这个客户端返回,做为标记,例如这个标签是 Joey
  2. 客户端收到cookie,在之后向服务端再发请求的时候会在头部的cookie字段加上服务端在上一步中发来的cookie,即 Joey
  3. 服务端收到了cookie: Joey, 就知道了这个用户是Joey, 而后就能够作进一步的操做了

1.2 cookie 的用处

Cookie主要用于如下三个方面:数组

  1. 会话状态管理(如用户登陆状态、购物车、游戏分数或其它须要记录的信息)浏览器

  2. 个性化设置(如用户自定义设置、主题等)缓存

  3. 浏览器行为跟踪(如跟踪分析用户行为等)安全

1.3 安全问题--cookie 是不可信的

cookie 是能够被修改的,客户端和服务端均可以对已经设置的cookie进行修改。服务器

在1.1部分的cookie设置过程当中可知,若是客户端将原本是 Joey的 cookie 改为 Ross,那么服务器就会认为如今发请求的客户端是 Ross,可能会给客户端 Joey 返回原本属于 Ross 的内容。这确定是不该该的。cookie

因此说, cookie 是不可信的。网络

1.4 cookie 的体积限制

客户端在得到服务端返回的 cookie 后,在之后再给服务器发请求时,不管服务端是否是想要 cookie, 都会放在请求里发过去。

咱们知道,网络请求是很是耗时间的,若是cookie过大,每次请求服务器时都会在 header 中带上 cookie ,则网络请求时间会过长。

因此大多数浏览器都对每一个域的cookie数量和大小有限制,每一个浏览器对cookie数量的限制不相同,但对总大小的限制大都是4096B。

若是新加入的cookie要超过了浏览器的最大数量限制,会删除较早的 cookie 以腾出空间。不一样浏览器的删除策略不一样,有的会删除最近最少使用的 cookie,例如 IE和Opera;有些彷佛会随机选择一个来删除,例如 Firefox...

若是新的加入新的 cookie 以后全部 cookie 的总大小超过限制,则新的 cookie 不会设置成功, 会被丢弃。

因此,不要设置太多 cookie, 以避免出现意料不到的事情。

1.5 cookie 的构成

cookie由如下几个字段组成:

  1. name:名称,惟一值,用来惟一识别cookie,不分大小写。必须通过 URL 编码
  2. value:值,对应于名称,必须通过 URL 编码
  3. domain:域,设置cookie对于哪一个域是有效的,都向这个域里发cookie。例如domain值为www.baidu.com,则全部发向这个网址的请求,都会发这个cookie
  4. path:路径,指定域里的路径能够接受这个cookie,例如百度下的/search路径:www.baidu.com/search
  5. expires:过时时间,表示这个cookie何时应该被删除,这是个日期格式的。若是没有定义,cookie会在对话结束时过时。若是想让一个cookie立刻过时,则能够将这个值设置成过去的时间。
  6. max-age:过时倒计时,以秒为单位。若是设置成0,则这个cookie马上失效,设置负数时不会产生cookie文件
  7. secure :设置该 cookie 只经过https协议传输,这不是键值对,是个标记,写上就表明设置为只在使用 https 传输。从 Chrome 52 和 Firefox 52 开始,不安全的站点使用http协议的站点没法使用Cookie的 Secure 标记
  8. http-only:设置不容许在浏览器端用 JavaScript 获取到 cookie。这也不是个键值对,是个标记,写上就表明生效。能够用来防止跨域脚本(XSS )攻击
  9. samesite:要求cookie在跨站请求时不会被发送,防止跨站请求伪造(CSRF)的特性,可取值

其中除name: value为必须以外,其他都是可选项。

1.6 在客户端用 JavaScript 操做 cookie

在客户端使用 JavaScript 对 cookie 的操做能够分为两类,分别是读取 cookie 和 设置 cookie,下面分别进行讨论。

BOM 的提供的操做 cookie 的 api 看起来有些难用。

1.6.1 读取 cookie

使用 document.cookie 便可得到该页面中全部的 cookie,例如,咱们来看看百度学术给我设置了什么cookie。打开http://xueshu.baidu.com/。按F12,打开上部分的 Application 选项卡,而后打开左侧的 cookies。

百度学术在个人电脑里保存的cookie如图:

而后在命令台上经过 document.cookie 来获取页面里的 cookie:

// 获取 cookie, 获得的是全部 cookie 组成的字符串
let cookies = document.cookie;
// 提取出全部的 cookie 到数组中
let cookieArray = cookies.split(';');
// 用 console.table 输出cookie数组,这样比较清晰
console.table(cookieArray);
复制代码

结果以下:

能够看到经过 document.cookie 获取的 cookie 的 name 和 value 与浏览器工具获得的相同。

以图中第一个cookie为例,cookie 名为 PSTM , value 是1563885xxx,域名是 .baidu.com,过时时间是2087年8月10号,其余属性都取默认值。

1.6.2 设置 cookie

给 document.cookie 赋一个新的 cookie 字符串能够设置一个新的 cookie 了。

以MDN为例,在这个网站域名下设置一个本身的cookie,配置以下:

  • cookie 名为 username,
  • cookie 值为 test,
  • domain为 .mozilla.org
  • path为 /

其余选项不设置,也就是取默认值。

设置以前的 cookie 为:

设置:

let name = 'username',
	value = 'test',
	domain = '.mozilla.org',
	path = '/';

var myCookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + ';domain=' + domain + ';path=' + path;

document.cookie = myCookie;
复制代码

结果以下:

能够看到 cookie 设置成功了。

1.7 服务端设置 cookie 发送给客户端

因为不一样服务端程序的在响应报文的头部设置 set-cookie 操做的具体代码不一样,这里以 node.js 的 koa 框架为例。

先起一个极简的 server,而后对于访问者返回的报文的 header 都设置 set-cookie 头部:

const Koa = require('koa');
const app = new Koa();

app.use(async ctx => {
  ctx.cookies.set('koa_cookie_name', 'koa_cookie_value');
  ctx.body = 'cookie setted';
});

app.listen(3001, (e) => {
    console.log('server listening port 3001');
});
复制代码

进入'http://localhost:3001/'后去查看 cookie:

能够看到服务端传来的 cookie。

2. sessionStorage 和 localStorage

sessionStorage 和 localStorage 有与cookie不一样的两点:

  1. 存储的数据被严格限制在本地
  2. 不会每次向服务器请求时都带上存储的数据

2.1 总述

sessionStorage 和 localStorage 都是 Storage 对象;都是以名值对的形式存储数据,存储数据的key和value都是字符串(string)类型,若是传入的不是字符串类型,会被转换为字符串类型。

因此,若是想把非字符串类型的数据存进来,要预先手动进行编码,取出来后要再进行解码。

2.2 增删改查数据的方法

这两类对象有着相同的增删改查数据的 api,因此能够用其中的一个对象为例子,来演示这些 api,这里选择 sessionStorage :

  1. setItem(key, value):将一个键值对的保存,若是两次保存的key相同可是value不一样,则后面的覆盖前面的。
  2. getItem(key):获取指定 key 对应的 value
  3. removeItem(key):删除指定的 key 及其 value
  4. key(index):获取指定位置的...
  5. clear():删除全部数据

还有一个属性:

  • length属性:判断存了多少名值对,上面key(index)方法中的参数 index 的范围是 0 =< index <= length - 1

使用sessionStorage来演示上面的 api:

存入两个键值对,使用 setItem(key, value)方法:

sessionStorage.setItem('key 1', 'value 1');
sessionStorage.setItem('key 2', 'value 2');
复制代码

打开浏览器页面的开发者工具,点击Application选项卡,点击左侧的 session Storage,就能看到两条刚刚保存的键值对了。

获取两个键对应的数据,使用 getItem(key)方法:

let value1 = sessionStorage.getItem('key 1');
let value2 = sessionStorage.getItem('key 2');

console.log(value1, value2); // value 1 value 2
复制代码

删除 'key 1'和其对应的数据,使用 removeItem(key)方法:

sessionStorage.removeItem('key 1');
复制代码

从图中能够看到存储的数据只剩下 key 2: value 2 了。

如今再添加几条数据:

sessionStorage.setItem('key 3', 'value 3');
sessionStorage.setItem('key 4', 'value 4');
sessionStorage.setItem('key 5', 'value 5');
sessionStorage.setItem('key 6', 'value 6');
复制代码

获得:

输出如今存储的数据条数,也就是键值对的条数,并输出最后一条,使用length属性:

let key_value_count = sessionStorage.length;
console.log('如今存储了 ' + key_value_count + ' 条数据'); // 如今存储了 5 条数据
复制代码

一次性删除全部数据,使用 clear()方法:

sessionStorage.clear();
复制代码

结果:

plus: 使用对象属性语法设置与访问数据

因为 Storage 自己就是对象,因此也可使用通常对象的读取与设置属性的语法来存取对象,本质就是经过设置属性和值的键值对来添加与读取数据。

存取的方式也和普通对象同样有两种,分别是点号法和中括号语法,例以下面的例子:

sessionStorage.key1 = 'value 1';
console.log(sessionStorage.key1);

sessionStorage['key 2'] = 'value 2';
console.log(sessionStorage['key 2']);
复制代码

结果如图:

这种语法和 api 中的 setItemgetItem效果相同。

想删除一个数据时,可使用 delete关键字,和删除普通对象属性的操做相同:

delete sessionStorage.key1;
delete sessionStorage['key 2'];
复制代码

结果:

这和 removeItem的效果相同。

2.3 两个 storage 的区别

sessionStorage 和 localStorage 的区别在声明周期和做用域这两点上,具体来讲以下。

  1. 在声明周期上
    • sessionStorage :
      1. 当浏览器的标签页被关闭时, 其中存的数据也会被删除。
      2. 对于 Chrome 和 Firefox 来讲,浏览器若是崩溃了,重启以后的仍然会保存原来的数据。
      3. 对于一些有从新打开标签页功能的浏览器,用户在关闭标签页后 sessionStorage 中的数据仍然存在。
    • localStorage : 当用户手动清除浏览器的缓存时,它其中的数据才会被清除。
  2. 在做用域上
    • sessionStorage :不一样标签页没法相互访问 sessionStorage 中保存的数据,即便这两个标签页访问的是同一个页面
    • localStorage :
      1. 访问同协议、同域名、同端口的页面共享一个 localStorage 。并且全部页面都有修改的能力。
      2. 利用上面的特色,可使不一样的标签页互相通讯,这要配合下面要说的 Storage 事件来讲。

2.4 storage 事件

在 Storage 里的数据被添加、修改、删除时,会触发 storage 事件,能够在 window 对象上添加事件监听程序 onstorage 来监听事件,而且能够获取事件对象。

storage 事件对象上有以下几个属性:

  1. key: 设置或删除的键名
  2. storageArea: localStorage 或 sessionStorage
  3. newValue: 修改后的值,若为删除操做则为 null
  4. oldValue: 被更改以前的值
  5. url: 所在的地址

注意:localStorage 的事件采用的是广播机制,正在访问相同站点的页面都会受到信息。这样能够完成必定的标签页之间的通讯。

参考:

MDN

《JavaScript高级程序设计》

《JavaScript权威指南》

相关文章
相关标签/搜索