存储方式详解(cookie、session、Token)

文章目录

    • 发展
  • 一、cookie
      • 注意点:
  • 二、session
      • cookie和session区别
  • 三、token
      • Token(令牌)认证机制(对比签名)
      • Token生成原理:
  • 总结cookie、localStorage、sessionStorage、indexDB
    • cookie:
    • LocalStorage
    • sessionStorage
    • indexDB

参考文献
HTTP无状态协议到底指的什么?
浏览器提供的几种存储
vuex页面刷新数据丢失的解决办法
Session Cookie Token 俊
彻底理解

发展


1、在很久以前,Web的工作只是文档浏览的一种方式,无论谁发请求给服务器,它都返回一样的文档,每一个请求对服务器而言都是全新的,是无状态的,不会记住刚刚是谁发的http请求。

2、但是随着Web应用的兴起,出现了像购物网站,需要登录的网站,就会面临一个问题,那就是要管理会话,必须知道是哪些人登录系统,哪个用户发来的请求。也就是说要区分不同的用户。但http是无状态请求的

什么是无状态呢
就是一旦客户端和服务器的数据交换完毕,就会断开连接,再次请求时才会重新连接,此时服务器无法判断用户身份,此时cookie和session就出现了。就是为了解决http无状态请求这个问题的


一、cookie

存储方式详解(cookie、session、Token)_第1张图片
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用Response HeaderSet-Cookie向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来(自动保存起来了,不用手动保存)。当浏览器再请求该网站时,浏览器通过Request HeaderCookie把请求的网址连同该Cookie一同提交给服务器(也是自动带上的cookie的)。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

注意点:

存储位置(客户端):

  1. 设置过期时间失效(只要设置了过期时间cookie就会存储在硬盘里面)
  2. 当会话结束时失效,即关闭浏览器窗口(如果没有设置Expires,cookie就会存储在内存里面

缺点:

  1. 因为是存储在客户端,所以不安全,有可能会被获取伪造(可以考虑加密)
  2. 存储量有限、不超过4k

当 Cookie 带 httpOnly 选项时,客户端则无法通过 js 代码去访问(包括读取、修改、删除等)这个 Cookie。

二、session

除了使用Cookie一种方法,Web应用程序中还经常使用第二种方法Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
存储方式详解(cookie、session、Token)_第2张图片
1、用户向服务器发送用户名和密码
2、服务器通过验证后,会在当前会话(session)里面保存相关数据,比如用户角色,登陆时间等;
3、服务器会通过Response Header的Set-Cookie向用户返回一个sessionId,客户端存入Cookie中
4、用户随后的每一次请求,都会通过Request Header的Cookie,将sessionId发送给服务器
5、服务器收到 sessionId 后,找到之前保存下来的数据,由此得知用户身份

注意点:

  1. 存储位置:服务器中(磁盘文件或数据库里面)
  2. 因为保存在服务端,所以相对于保存在客户端的cookie来说更加安全了

cookie和session区别

Cookie和Session的区别

  1. 存储位置不同:cookie存储在客户端,session存储在服务端
  2. 存储容量不同:cookie最多能保存4KB的数据,session来说没有上限,所以高并发时,session会很耗服务器资源
  3. 存储方式不同:cookie只能保存ASCLL字符串,session能够保存任何类型的数据
  4. 安全性:cookie对客户是可见的,可能会被伪造,session存储在客户端的,相对安全
  5. 有效期不同:cookie可以手动设置有效时间,session在关闭会话窗口之后就会丢失失效

三、token

引入背景(session不足):

1、服务器压力增大:
session是保存在服务端的,客户端只需要保存自己的sessionId,但是服务端要保存所有用户的sessionId,如果访问服务器的人多了,可能有几十万,几百万,这对服务器来说是一个巨大的开销。

2、CSRF跨站伪造请求攻击:
session是基于cookie进行用户识别的,cookie如果被获取,用户就有可能受到CSRF的攻击

3、拓展性不强:
如果将来搭建了多个服务器,比如用多个服务器组成的一个集群,虽然每个服务器处理的业务逻辑都是一样的,但session是保存在服务器里面的,多个服务器之间是不共享的,用户第一次访问服务器A,A将该用户的session保存起来,但是当用户下一次请求的是服务器B,此时B里面就找不到该用户的信息,就判定该用户不合法。

针对session拓展性不强,人们想出了一些小伎俩:

  • session sticky:就是让用户一直访问同一个服务器,俗话说就是黏在一起。但是对应的服务器也会有挂掉的时候,所以不管用
  • session复制,就是让不同服务器都有相同session,从一个服务器复制到其他服务器
  • 把session集中存储到一个地方,所有服务器都来访问此机器。但是此机器也会有挂掉的时候

对小小的session来说,以上的方法都不好,负担沉重

由此,token就应运而生

Token(令牌)认证机制(对比签名)

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

Token把状态交给用户来管理,这样的确解决了空间问题,但是如果服务器不保存这些会话标识(session要保存在服务器端),我们又改如何确定这些会话标识是不是由我生成的呢。如果无法验证他们是不是合法的,就无法保证登陆的安全性

Token解决这个问题的关键在于验证

验证的关键的生成一个签名,一般服务器运用哈希算法(比如HMAC-SHA256),加上只有服务端才知道的密钥,对数据(比如userId)做一个签名,把这个签名和数据一起作为token发给客户端,由于密钥别人不知道,所以不能伪造token
存储方式详解(cookie、session、Token)_第3张图片
这个token服务端不用保存,当客户端把这个token发过来时,服务端再用同样的哈希算法对数据做一个签名,看看此时生成的签名和token带回来的签名是否一致,如果一致,我知道用户已经登录过来,并且可以直接获取到用户的id。
存储方式详解(cookie、session、Token)_第4张图片
存储方式详解(cookie、session、Token)_第5张图片
其验证过程如下:

  1. 客户端使用用户名跟密码请求登录
  2. 服务端收到请求,去验证用户名与密码
  3. 验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  4. 客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
  5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  6. 服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

Token的验证是无状态的,我们不用将用户信息保存在服务端,每一次请求都要带上token,token应该在http的头部发送从而保证了http请求无状态。这样我们就可以减轻服务端的压力,实现了用计算时间(因为进行加密解密需要消耗时间)换取空间,session是空间换时间同时也增强了可拓展性

Token生成原理:

什么是token及怎样生成token、《JSON Web Token 简介》

  1. 将荷载payload,以及Header信息进行Base64加密,形成密文payload密文,header密文。
  2. 将形成的密文用点号链接起来,用服务端秘钥进行HS256加密,生成签名.
  3. 将前面的两个密文后面用点号链接签名形成最终的token返回给服务端。jwt最终形成的字符串结构如:xxxxx.yyyyy.zzzzz,每一部分都是基于base64url编码的值
    存储方式详解(cookie、session、Token)_第6张图片

token优势:
1、无状态、可扩展
在客户端存储的Tokens是无状态的,并且能够被扩展。基于这种无状态和不存储Session信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。如果我们将已验证的用户的信息保存在Session中,则每次请求都需要用户向已验证的服务器发送验证信息(称为Session亲和性)。用户量大时,可能会造成 一些拥堵。但是不要着急。使用tokens之后这些问题都迎刃而解,因为tokens自己hold住了用户的验证信息。

2、安全性

请求中发送token而不再是发送cookie能够防止CSRF(跨站请求伪造)。即使在客户端使用cookie存储token,cookie也仅仅是一个存储机制而不是用于认证。不将信息存储在Session中,让我们少了对session操作。token是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到token自动失效,token有撤回的操作,通过token revocataion可以使一个特定的token或是一组有相同认证的token无效。

3、可扩展性

Tokens能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook或是Twitter)联系起来。当通过服务登录Twitter(我们将这个过程Buffer)时,我们可以将这些Buffer附到Twitter的数据流上(we are allowing Buffer to post to our Twitter stream)。使用tokens时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的API,得出特殊权限的tokens。

4、多平台跨域

我们提前先来谈论一下CORS(跨域资源共享),对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。Having our API just serve data, we can also make the design choice to serve assets from a CDN. This eliminates the issues that CORS brings up after we set a quick header configuration for our application.只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。Access-Control-Allow-Origin: *


总结cookie、localStorage、sessionStorage、indexDB

cookie:

Cookie实际上是一小段的文本信息。是为了解决http无状态请求的问题。客户端请求服务器,如果服务器需要记录该用户状态,就使用Response HeaderSet-Cookie向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来(自动保存起来了,不用手动保存)。当浏览器再请求该网站时,浏览器通过Request HeaderCookie把请求的网址连同该请求域下(请求谁就带上谁的cookie)的Cookie一同提交给服务器(也是自动带上的cookie的)。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。

cookie属性 作用
name字段 一个cookie的名称
value 一个cookie的值
domain 可以访问此cookie的域名
path 可以访问此cookie的页面路径
Size cookie大小
httponly 若此属性为True,客户端则无法通过 js 代码去访问(包括读取、修改、删除等)这个 Cookie。
secure 设置是否只能在https下来传递此条cookie。
expires/Max-Age 设置cookie超时时间。如果设置的值为一个时间,则当到达该时间时此cookie失效。不设置的话默认是session,意思是cookie会和session一起失效,当浏览器关闭(并不是浏览器标签关闭,而是整个浏览器关闭)后,cookie失效。
SameSite 不跨站发送cookie到第三方网站,减少 CSRF 的攻击;Strict(仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致);Lax(允许部分第三方请求携带 Cookie,除了get请求可以);None(无论是否跨站都会发送 Cookie);之前默认是 None 的,Chrome80 后默认是 Lax

《预测最近面试会考 Cookie 的 SameSite 属性》、《阮一峰Cookie 的 SameSite 属性》

使用:

  • document.cookie='名字=值'

cookie不足:

  • 大小:一个cookie的大小被限制在4KB。每个域名有数量限制(不同浏览器可能不同,ie的话限制50个)
  • 带宽:cookie是随HTTP事务一起被发送的,因此会浪费一部分发送cookie时使用的带宽。过多的Cookie会带来巨大的性能/资源浪费。Cookie是紧跟域名的,同一个域名下的所有请求都会携带Cookie。很多场景其实并不需要身份验证,比如请求一张图片或者CSS文件,这种时候携带Cookie也就造成了性能/资源的浪费

4kb指的是:
《Cookie有数量和大小的限制》、《浏览器cookie数量和大小限制》
各浏览器的cookie每一个name=value的大小大概在4k;所以4k并不是一个域名下所有的cookie共享的,而是一个名(name)、值(value)和等号(=)的大小;而对于每个域名name个数的限制,发现ie10大概是50个,如果超过了50个,最前面设置的就会挨删除把新的放进去.当出现这种溢出替换的过程时,就会导致当前进程的ie的这个域名无法访问,需要重启浏览器才行;

为了弥补Cookie的局限性,WebStorage就产生了。WebStorage是HTML5中新增的本地存储解决方案,包含了SessionStorage和LocalStorage两类。有了WebStorage之后,Cookie就能够安心只作为客户端与服务器交互的通道(保持客户端状态)了,不用再操心存储的事情。

WebStorage两个主要目标:
(1)提供一种在cookie之外存储会话数据的路径。
(2)提供一种存储大量可以跨会话存在的数据的机制。

LocalStorage

将数据保存在客户端本地的硬件设备(通常指硬盘,也可以是其他硬件设备)中,即使浏览器被关闭了,该数据仍然存在,下次打开浏览器访问网站时仍然可以继续使用。

特点(默认也不能跨域访问):

  • 保存的数据长期存在
  • 存储限制大小为5MB左右(每个域名下),超过5m不会把旧数据清空而只会报错
  • 仅在客户端使用,不和服务端进行通信

使用:

  • localStorage.setItem(name, val);
  • localStorage.getItem(name);

使用场景:

  • 倾向于用它来存储一些内容稳定的资源。比如图片内容丰富的电商网站可以使用LocalStorage来存储Base64格式的图片字符串。

sessionStorage

译-在多个标签页之间共享sessionStorage
将数据保存在session对象中。所谓session,是指用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。session对象可以用来保存在这段时间内所要求保存的任何数据。

特点:

  • 会话级别的浏览器存储,数据只在当前标签页有效,关闭标签页则删除了
  • 每个标签页都是一次会话,只在当前会话生效。(只能在同一标签页下共享)
  • 存储限制大小为5MB左右(每个域名是5M

使用:

  • sessionStorage.setItem('key','value')
  • sessionStorage.getItem('key');

使用场景:

  • SessionStorage更适合用来存储生命周期和它同步的会话级别的信息,这些信息只适用于当前的会话。比如微博就使用SessionStorage存储单次会话的浏览足迹

tip:这两者的区别在于,sessionStorage为临时保存,而localStorage为永久保存。

indexDB

IndexedDB是一种低级的API,使用索引来实现对其间存储数据的高性能搜索,用于客户端需要存储大量结构化数据。他可以看作是一个运行在浏览器上的非关系型数据库。既然是数据库了,那就不是5M、10M这样小打小闹的级别了,理论上来说,IndexedDB是没有存储上限的,一般来说不会小于250M。另外,它不仅可以存储字符串,还可以存储二进制数据

你可能感兴趣的:(http与计算机网络)