Cookie、Session和Web Storage

Posted by Mars . Modified at

浏览器端、服务器端储存数据的几种方式:cookie,session,localStorage,sessionStorage,indexedDB

全面整理,包含以前的笔记。

一、Cookie

1. Cookie的作用

HTTP是无状态协议。Cookie的存在,是为了让服务器能识别连接过它的用户,从而在响应上针对性地采取一些友好措施。

比如一个购物网站,如果服务器无法识别客户是谁,是否曾经连接过服务器并进行某些操作。那么每次重新访问网站服务器,都需要重新登录,购物车里的东西也会被清零,因为服务器无法识别每次连接的客户。

Cookie是直接保存在浏览器中的一小段数据,在每次请求相同的域的时候(根据cookie的domain/path/samesite设置),会自动携带cookie首部,供服务器进行识别。

cookie与域直接关联。所在页面与cookie绑定的域相同,则称为第一方cookie。否则称为第三方cookie

2. Cookie的典型应用场景

Refer: 浅谈session,cookie,sessionStorage,localStorage的区别及应用场景

  1. 判断用户是否登陆过网站,以便下次登录时能够实现自动登录(或者记住密码);
  2. 保存上次登录的时间等信息;
  3. 保存上次查看的页面;
  4. 浏览计数。

3. Cookie的工作方式

当用户浏览某一个使用了Cookie的网站,则:

① 网站的服务器就生成一个该用户的识别码(唯一);

② 网站以此识别码为索引在服务器后端建立一个数据库项目;

③ 然后在给用户回复的HTTP响应报文中添加一个首部行:

Set-cookie:<唯一Cookie识别号>

④ 当客户收到响应报文,浏览器就在管理Cookie的文件中添加一行,其中包括这个服务器的主机名和它响应的识别码。

⑤ 当客户再次向这个服务器发送请求报文,浏览器就会自动地从管理Cookie的文件中抽出这个Cookie,并添加在请求报文的首部行中。

Cookie:

4. Cookie的结构、JS设置和体积限制

在打开页面的控制台输入document.cookie,可以查看某一个网站的cookie。结构如下:

某网站的Cookie:

“_ga=GA1.2.1788237449.1610895464; _ym_d=1610895465; _ym_uid=1610895465705583085; _gid=GA1.2.529167652.1619787501; _ym_visorc=w; _ym_isad=2; pixelRatio=1.75”

document.cookie 的值由 name=value 对组成,以 ; 分隔。每一个都是独立的 cookie。

通过document.cookie也可以设置当前域的cookie,Cookie的修改具有独立性: document.cookie = ‘cookieProperty=cookieContent;’ 这一设置,只会在cookie中添加(或修改已存在的)一个cookieProperty的值,不会覆盖全部的cookie。(document.cookie接口是一对getter/setter,因此get和set的操作方式不同)

通过document.cookie设置的cookie,都只能作用于当前域。

Cookie的体积大小不能超过4kB,条目数一般不能超过20条,具体与浏览器实现相关。

5. Cookie中的特殊字段

5.1 path

设置浏览器发送Cookie的url路径前缀。只有这个路径下的页面可以访问到这个Cookie。默认是’/’

一般设置 path=/;

这样这个域名下所有网页都可以访问到这个Cookie。 如果设置 path=/main 则只有main子目录的页面可以拿到Cookie

5.2 domain

设置可访问Cookie的域名。

默认情况下domain等于当前域名。也就是说,www.marswiz.com下设置的 cookie,只能在这个域访问,即使是它的父级域marswiz.com也不行。

设置了 domain = site.com; 则 *.site.com 的所有域名都能拿到这个cookie(父域和子域)。

5.3 expires, max-age

expires是Cookie的到期日期,到期后Cookie被浏览器自动删除。

expires 需采用 GMT 时区格式,可以用 date.toUTCString 来获取它。

max-age是Cookie的存活时长,为一个数字,单位是秒。

expires和max-age二者设置其一就可以。

5.4 secure

规定这个Cookie只能被Https协议传输。

默认情况下,Cookie不区分协议,只区分域。

5.5 samesite

samesite关键字有三种取值:

  • strict: 只有同站
  • lax:
  • none:

cookie如何判断是同站?

cookie判断同站,是根据eTLD+1方法。

也就是:有效的顶级域名+二级域名相同,则判断同站,否则是非同站。

www.taobao.com 和 www.baidu.com 是跨站,www.a.taobao.com 和 www.b.taobao.com 是同站,a.github.io 和 b.github.io 是跨站(注意是跨站,因为github.io是注册的顶级域名)。

samesite关键字防止了一种叫做CSRF(Cross-Site Request Forgery 跨网站请求伪造)的攻击:

当用户已经在某一网站(site.com)完成登录认证,服务器返回了用户的Cookie并保存在浏览器中。默认情况下,只要从浏览器向site.com域发送请求,都会携带这个Cookie,服务器就会识别为认证的用户。

这时,如果用户访问了一个带有恶意请求代码(比如)的网站(evil.com),请求会带着Cookie发送到服务器,从而代表用户执行了恶意操作。

5.6 httpOnly(服务器端设置)

这个关键字在浏览器本地无法设置,只能在服务器端set-cookie的时候设置。

设置了httpOnly的Cookie,在浏览器中无法用JavaScript访问,也就是document.cookie看不到。(防止黑客获取到Cookie)

6. 什么时候会携带cookie?

根据cookie的几个关键字设置,浏览器自动判断发出请求时是否携带cookie。

  • domain: cookie的域名;
  • path: cookie的路径;
  • samesite: 是否同站;

二、session

session也叫作”会话控制”,是用户第一次向服务器请求连接时,由服务器生成的一个唯一标识,用于区别用户,并对用户进行权限隔离。

session 认证流程:

  • 用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session
  • 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器
  • 浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名
  • 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到Session 证明用户已经登录可执行后面操作。

session在客户端的储存位置:

  • cookie中(最佳);
  • url中(需重写URL);

session与cookie的主要区别:关闭浏览器后(或者长时间没有任何往来,超过了服务器设定的会话有效期),Session自动失效。

session将重要信息保存在服务器,仅将session_id等简要信息保存在客户端,相对cookie更安全。

移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token。

三、localStorage 与 sessionStorage

1. 概述

localStorage 与 sessionStorage 都用来在浏览器中保存键值对。(HTML5中提供)

localStorage 与 sessionStorage的键和值都必须是字符串,传入其他类型也会自动转换为字符串。

它们比Cookie的好处(区别)在哪?

  1. 不会像Cookie一样,随着每次请求一块发送到服务器;
  2. 保存的数据量更大,一般至少有2MB;
  3. 只能通过纯JavaScript操作,无法通过http等协议修改;
  4. Cookie是绑定到的(与协议和端口无关),而 localStorage 是绑定到的,也就是必须同一“协议+域名+端口”,才能访问同一 localStorage;
  5. sessionStorage只在当前标签页下有效,数据也只存在于当前浏览器标签页。

2. 应用场景

  • 保存用户在页面的输入内容,比如表单、文本等,防止刷新或重新访问后消失;
  • 快速响应:静态文件第一次请求后储存在localStorage,后续从localStorage直接读取,加快响应速度;
  • sessionStorage 的使用情况非常少。

3. localStorage 与 sessionStorage的通用方法

  • setItem(key, value) —— 存储键/值对。
  • getItem(key) —— 按照键获取值。
  • removeItem(key) —— 删除键及其对应的值。
  • clear() —— 删除所有数据。
  • key(index) —— 获取该索引下的键名。
  • length —— 存储的内容的长度。

4. localStorage 和 sessionStorage 的区别

  • localStorage用于本地长期储存,它的生命周期是永久的,除非用户手动删除或清空;
  • sessionStorage只在本次会话窗口(标签页)有效,窗口关闭就清空;
  • localStorage是绑定源的,“协议+域名+端口”相同的URI就可以访问,本地多个同源标签页共享同一localStorage;
  • sessionStorage是绑定标签页的,不同标签页即使同源也不共享sessionStorage,但是一个标签页内的iframe可以获取到该页面的sessionStorage。

5. 有关localStorage和sessionStorage的事件

每次更新localStorage和sessionStorage中的数据,storage事件就会发生,它的触发对象是所有能获取到该localStorage和sessionStorage的全局对象window

window.addEventListener('storage',(e)=>{
    console.log('storage changed.')
})

这个事件对象e具有如下属性:

  • key —— 发生更改的数据的 key(如果调用的是 .clear() 方法,则为 null)。
  • oldValue —— 旧值(如果是新增数据,则为 null)。
  • newValue —— 新值(如果是删除数据,则为 null)。
  • url —— 发生数据更新的文档的 url。
  • storageArea —— 发生数据更新的 localStorage 或 sessionStorage 对象。

所有能获取到更新的localStorage的window,都会被触发storage事件,这提供了一种跨标签页传递数据的方式:

比如:同时打开了两个同源的标签页,页面上同时监听了storage事件,回调函数是打印一个数据。

那么在一个标签页修改localStorage数据之后,另一个标签页会响应这个storage事件,同时也会打印这个数据。

四、indexedDB

1. 什么是indexedDB?

indexedDB是浏览器内置的一个数据库,它比localStorage更强大:

  1. 支持多种类型的键,储存多种JS类型的值;
  2. 更大的储存容量(一般至少250MB,甚至没有上限);
  3. 支撑事务(事务是一组同时成功或失败的操作),保证数据操作的可靠性;
  4. 支持键的范围查询(min,max等)、索引。

2. indexedDB 应用场景

在传统的浏览器-服务器页面应用有限,indexedDB主要应用于web离线应用。

3. indexedDB的使用方式

indexedDB也是绑定到源的,不同源的页面无法访问同一个indexedDB.

  • ① 要使用一个indexedDB数据库,需要先打开它;

let openRequest = indexedDB.open(name, version);

name —— 字符串,即数据库名称。

version —— 一个正整数版本,默认为 1。

  • ② indexedDB数据库中可创建对象库用来存储特定数据,通过事务进行数据操作;
  • ③ 通过键、范围或索引可以查询数据;

indexedDB使用的较少,具体使用方式参考:

IndexedDB 现代JS教程

previousPost nextPost
已经有 1000000 个小伙伴看完了这篇推文。