有关Cookie、Session、Token以及Storage

本文最后更新于 2024年4月9日 下午

因为一开始做的项目大部分都是WEB相关的,所以CookieSession是经常可以接触到的,但是只是知其然而不知其所以然。昨天再一次遇到,正好有时间于是便一次彻底地将其弄清楚了。

Cookie的工作方式

Cookie是浏览器提供的功能,是存储在浏览器中的纯文本文件,每个浏览器的安装目录下都应该有一个目录去存储这些文件。每次浏览器向一个域名发起HTTP请求时都会检查是否拥有该域名下的Cookie,如果拥有则在请求头中携带上。如下:

image-20210116113555581

Cookie可以在客户端(浏览器)存储一些经常用到的信息,如用户身份信息,以便用户每次请求都不必验证身份只要在Cookie携带约定好的信息,服务器就可以识别用户的身份。但是只有每次请求都携带的信息才适合存储在Cookie中,滥用Cookie会增加网络开销,在localStorage出现前Cookie就曾经被当作存储工具“滥用”。

Cookie的大小被限制为4KB,每个域名下的Cookie数量被限制为20个,当然这也不是绝对的,有些浏览器的数量可能要大于20个。Cookie的属性之间用一个分号和空格隔开。

Cookie的属性选项

Cookie的属性包括一些功能选项:expires/max-agedomainpathsecureHttpOnly,设置一个Cookie时可以选择通过设置这写选项来起到相应的功能,当然也可以不设置,若不设置这些值将被自动设置为默认值。

image-20210116120611983

expires

expires用来表示Cookie的失效时间,是一个GMT格式的数据对于失效的Cookie浏览器会自动清空,如果没有主动设置这一时间,那么Cookie会被自动设置为Session,即为“会话Cookie”这种Cookie在浏览器关闭后会被清除。

expireshttp/1.0协议中的选项,在新的http/1.1中这一选项已经被max-age选项取代。max-age指的是生命周期的时间(expires = Cookie的创建时间 + max-age )。max-age有三种取值,正数:有效期;零:Cookie应该删除;负数:Session类型的Cookie

domainpath

domain即为域名,path即为路径,二者加在一起便构成了url,url便决定了Cookie何时可以被访问,何时请求中会被自动添加Cookie

domain的默认值为当前网页的域名,path的默认值为当前的目录。

需要注意:

  1. 在发送XHR请求时,即使domainpath满足条件,但是浏览器也不会添加Cookie到请求头中。
  2. domain不可以设置为域名的公共后缀,如:.com.cn

secure

secure保证了Cookie只有在安全的请求中才会被发送,如请求使用的HTTPS等安全协议。默认情况下secure选项为空,即为不设置,所以这时候HTTPHTTPS请求都可以发送Cookie

但是需要注意的是,如果在客户端中想要修改Cookie中的secure选项,需要当前的网页使用的是HTTPS协议。

HttpOnly

这个选项用来设置Cookie是否能通过 js 去访问。默认情况下,Cookie不会带HttpOnly选项(即为空),所以默认情况下,客户端是可以通过js代码去访问(包括读取、修改、删除等)这个Cookie的。当CookieHttpOnly选项时,客户端则无法通过js代码去访问(包括读取、修改、删除等)这个Cookie

设置Cookie

服务端设置Cookie

服务端通过在响应头中加入set-Cookie字段对Cookie进行设置,一个set-Cookie字段只能设置一个Cookie。服务端可以对上文提到的全部Cookie选项进行设置。

image-20210116130800157

客户端设置Cookie

客户端可以通过以下语句对Cookie进行设置。

1
document.Cookie = "name=Jonh; ";

但是需要注意的是:

  1. HTTP网页无法对secure字段进行设置。
  2. 客户端无法对设置了HttpOnlyCookie进行更改。

修改 / 删除Cookie

  1. 修改Cookie只要保证domainpath不变的情况,对Cookie的其他情况进行修改就可以了。
  2. 删除Cookie同理,只要对expires字段进行更改,将其改为一个过期的时间就可以使浏览器删除该Cookie了。

Session

既然有了Cookie对用户的信息和状态进行标识为什么还要引入Session呢?因为Cookie是以明文传输的,他的作用是标识用户、记录状态等。那我们是不是可以用一个无实际意义的字串表示用户,防止敏感信息以明文暴露了。

因此,像签名这样敏感的信息是不应该在Cookie中以明文进行传输的,而是以Session存储在服务端,Session像是账本,这样的数据不会直接交给用户,而是只交给用户一个SessionID,也就是账户的户号。

Session一般存储在服务端的内存中,也可以存储在内存数据库中。一个Session会持续一段时间,通过Cookie中携带SessionID的方式可以做到持久访问的会话,这种会话便称为Session,每次用户访问都会更新Session的生命,长时间未访问的Session会被移出内存,保存至速度相对较慢的位置。Session也有一段时间的生命周期,过时会被清理。

Session 并不是某一种具体的实现而是一种方案,只要可以实现持久访问的会话的方案都可以称Session

Token

Token的理念与Session不同,Session是需要存储在后端,占用一定的空间,但是Token本身不占用空间,他只是将用户的敏感信息以一种加密的方式进行变换,实际上Token中携带的就是用户信息的加密变体。Token的使用可以参考JWT

  • Session:在后端保存了一个身份证数据库,交给用户一个身份证号,每次用户只需要用身份证号查询信息就可以了。耗费存储空间。同时还会遇到的一个问题是:“如果采用负载均衡的方式,可能上一次请求服务器A的时候将Session存储在了服务器上,下一次请求时因为负载均衡将我的请求发送到服务器B上,此时Session就不存在了。”
  • Token:将用户的身份证进行加密,加密后将身份证还给用户,每次校验用户信息与状态,只需要将其解密就可以了。耗费解密时间。

SessionID和Token都是以Cookie的形式在客户端进行存储的。

LocalStorage / SessionStorage

二者都属于浏览器端存储,是HTML5的新特性,都继承自Storage,因此语法和原理上有极高的相似性。

相同点:

  1. 可以通过下面的方式访问:

    1
    2
    window.localStorage
    window.`Session`Storage
  2. 两者的操作语法是一致的(这里以localStorage为例):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    localStorage.setItem("name", "carter");  // 设置name: carter

    localStorage.age = "24"; // 设置age: 24

    localStorage.getItem("name"); // 获取name的值carter

    localStorage.removeItem("name"); // 删除name

    localStorage.clear(); // 清空localStorage
  3. 均遵守同源规则

  4. 存储大小都为5MB

不同点:

  1. 失效时间不同
    • localStorage:不会失效,会永久保存,需要手动删除。
    • SessionStorage:跟会话绑定,会话结束即清除。但注意:刷新、回退不会清除。
  2. 有效范围不同
    • localStorage:同源跨标签可以共用。
    • SessionStorage:不同标签不能共用。

IndexedDB

尽管Storage5M的空间已经相对较大了,但仍然无法满足所有的前端存储需求。为此,HTML5规范推出了前端的事务型数据库indexedDB。它可以存储大量的结构化数据,具有几乎可以媲美后端数据库的读写性能。

感谢:

彻底理解Token、Cookie、Session

Session,Token相关区别

Cookie/Session 的机制与安全

聊一聊Cookie

五分钟带你了解啥是JWT


有关Cookie、Session、Token以及Storage
https://siegelion.cn/2021/03/02/有关Cookie、Session、Token以及Storage/
作者
siegelion
发布于
2021年3月2日
许可协议