# cookie&session&storage

  • Cookie 最开始被设计出来其实并不是做本地存储的,而是为了弥补 http 在状态管理上的不足
  • http 协议是一个无状态协议,客户端向服务器发请求,服务器返回响应,这次事件就完成了,但是下次发请求如何让服务端直到客户端是谁呢?在这个需求下就产生了 Cookie
  • Cookie 本质上就是浏览器里面存储的一个很小的文本文件,内部以键值对的方式来存储(在 chrome 开发者面版的 Application 这一栏可以看到)都会携带相同的 Cookie,服务器拿 Cookie 进行解析,便能拿到客户端的状态 Cookie 的作用就是用来做状态存储的,但是也有很多缺陷:
  1. 容量缺陷。Cookie 的体积上限只有 4KB,只能用来存储少量的信息
  2. 性能缺陷。Cookie 紧跟域名,不管域名下面的某一个地址需不需要这个 Cookie,请求都会携带上完整的 Cookie,这样随着请求数的增多,其实会造成巨大的性能浪费的,因为请求携带了很多不必要的内容
  3. 安全缺陷。由于 Cookie 以纯文本的形式在浏览器和服务器中传递,很容易被非法用户截取,然后进行一系列的篡改,在 Cookie 的有限期内重新发送给服务器,这是很危险的。另外,在 HttpOnly 为 false 的情况下,Cookie 信息能直接通过 js 脚本来读取。

前端可以通过 document.cookie 或者 CookieStore 来操作 cookie。Cookie 的作用域是和 domain(域名或 ip)绑定的,端口无关。

属性 作用
cookieName 属性名
HttpOnly 设置后客户端无法通过脚本读写 cookie
Expires 过期时间
Max-Age 有效时间长度,单位为秒。通过设置小于等于 0 的数字,可以让一个 cookie 失效
Path 设置 cookie 的路径作用域
Domain 设置 cookie 的 domain 作用域
Secure 设置为安全模式,没有 value 值,请求必须为 https 协议才会被保存下来
SameSite cookie 在跨域时是否应该被发送,value 为 Strict,Lax,None

# session

session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。

session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,一般都默认采用 cookie 的方式。

服务器使用 session 把用户的信息临时保存在了服务器上,用户离开网站后 session 会被销毁。这种用户信息存储方式相对 cookie 来说更安全,可是 session 有一个缺陷:如果 web 服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候 session 会丢失。

# Token

在 Web 领域基于 Token 的身份验证随处可见。在大多数使用 Web API 的互联网公司中,Token 是多用户下处理认证的最佳方式。

# Token 的起源

基于服务器的验证:

我们都是知道 HTTP 协议是无状态的,这种无状态意味着程序需要验证每一次请求,从而辨别客户端的身份。在这之前,程序都是通过在服务端存储的登录信息来辦别请求的。这种方式一般都是通过存储 Session 来完成。

随着 Web,应用程序,移动端的兴起,这种验证的方式逐渐暴露出了问题。尤其是在可扩展性方面。

基于服务器验证方式暴露的一些问题:

  • Seesion:每次认证用户发起请求时,服务器需要去创建一个记录来存储信息。 当越来越多的用户发请求时,内存的开销也会不断增加。
  • 可扩展性:在服务端的内存中使用 Session 存储登录信息,伴随而来的是可扩展性问题。
  • CORS(跨域资源共享):当我们需要让数据跨多台移动设备上使用时,跨域资源的共享会是一个让人头疼的问题。在使用 Ajax 抓取另一个域的资源,会出现禁止请求的情况。
  • CSRF(跨站请求伪造):用户在访问银行网站时,他们很容易受到跨站请求伪造的攻击,并且能够被利用其访问其他的网站。

基于 Token 的验证原理:

基于 Token 的身份验证是无状态的,我们不将用户信息存在服务器或 Session 中。这种概念解决了在服务端存储信息时的许多问题。

NoSession 意味着你的程序可以根据需要去增减机器,而不用去担心用户是否登录。

基于 Token 的身份验证的过程如下:

  1. 用户通过用户名和密码发送请求
  2. 程序验证
  3. 程序返回一个签名的 token 给客户端
  4. 客户端储存 token,并且每次用于每次发送请求
  5. 服务端验证 token 并返回数据

每一次请求都需要 token。token 应该在 HTTP 的头部发送从而保证了 HTTP 请求无状态。我们同样通过设置服务器属性 Access-Control-Allow-Origin:*,让服务器能接受到来自所有域的请求。

# Token 的优势

  1. 无状态、可扩展:在客户端存储的 Tokens 是无状态的,并且能够被扩展。基于这种无状态和不存储 Session 信息,负载负载均衡器能够将用户信息从一个服务传到其他服务器上。如果我们将已验证的用户的信息保存在 Session 中,则每次请求都需要用户向已验证的服务器发送验证信息(称为 Session 亲和性)。用户量大时,可能会造成一些拥堵。
  2. 安全性:请求中发送 token 而不再是发送 cookie 能够防止 CSRF(跨站请求伪造)。即使在客户端使用 cookie 存储 token, cookie 也仅仅是一个存储机制而不是用于认证。不将信息存储在 Session 中,让我们少了对 session 操作。token 是有时效的,一段时间之后用户需要重新验证。我们也不一定需要等到 token 自动失效,token 有撤回的操作,通过 token revocataion 可以使一个特定的 token 或是一组有相同认证的 token 无效。
  3. 可扩展性:Tokens 能够创建与其它程序共享权限的程序。例如,能将一个随便的社交帐号和自己的大号(Fackbook 或是 Twitter)联系起来。当通过服务登录 Twitter( 我们将这个过程称之为 Buffer)时,我们可以将这些 Buffer 附到 Twitter。使用 token 时,可以提供可选的权限给第三方应用程序。当用户想让另一个应用程序访问它们的数据,我们可以通过建立自己的 API,得出特殊权限的 token。
  4. 多平台跨域:CORS(跨域资源共享),对应用程序和服务进行扩展的时候,要介入各种各种的设备和应用程序。只要用户有一个通过了验证的 token,数据和资源就能够在任何域上被请求到。 Access-Control-Allow-Origin:*

# WebStorage

localStorage 进阶知识

对比 cookie 的优点:

  • cookie 存放数据太小,Cookie 的存储大小只有 4k
  • cookie 每次都会携带在 HTTP 请求头中,会与服务端进行一些交互,单纯存储一些本地数据时,很明显会造成性能浪费

sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面,仅在当前浏览器窗口关闭之前有效