cookie、session、localStorage、sessionStorage

481 阅读7分钟

数据存储

Cookie的由来

学过http的同学都知道,http是一种不保存状态的协议,即无状态(stateless)协议。

什么是不保存状态?

  • http协议自身不对请求和响应之间的通信状态进行保存,协议本身并不保留之前一切的请求或响应报文的信息,也就是一个服务器是不清楚是不是同一个浏览器在访问它的。举个栗子,假设要求登录认证的web页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转页面就要再次登录。
  • HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术。有了 Cookie 再用 HTTP 协议通信,就可以管理状态了。通过在请求和响应报文中写入cookie信息来控制客户端的状态。

Cookie的原理

Cookie原理

Cookie的构成(属性)

  • 名称(name): cookie 名称是不区分大小写的,不过实践中最好将 cookie 名称看作是区分大小写的,因为某些服务器会这样处理 cookie。cookie 的名称必须是经过 URL 编码的。
  • 值(value): 储存在 cookie 中的字符串值。值必须被 URL 编码。要解码的话必须使用decodeURIComponent()来解码。
  • 域(domain): cookie 有效的域。发送到这个域的所有请求都会包含对应的 cookie。这个值可能包含子域(如www.wrox.com),也可以不包含(如.wrox.com 表示对 wrox.com 的所有子域都有效)。如果不明确设置,则默认为设置 cookie 的域。
  • 路径(path): 请求 URL 中包含这个路径才会把 cookie 发送到服务器。例如,可以指定 cookie 只能由 www.wrox.com/books/ 访问,因此访问 www.wrox.com/ 下的页面就不会发送 cookie,即使请求的是同一个域。
  • 失效时间/有效期(Expires/Max-Age): 默认情况下,浏览器会话结束时即将所有 cookie 删除;不过也可以自己设置删除时间。Max-Age,是以秒为单位的,Max-Age为正数时,cookie会在Max-Age秒之后,被删除,当Max-Age为负数时,表示的是临时储存,不会生出cookie文件,只会存在浏览器内存中,且只会在打开的浏览器窗口或者子窗口有效,一旦浏览器关闭,cookie就会消失。
  • 安全标志(secure): 当这个属性设置为true时,此cookie只会在https和ssl等安全协议下传输(发送给服务器) 。
  • HttpOnly: 如果这个属性设置为true,就不能通过js脚本来获取cookie的值(document.cookie),能有效的防止XSS攻击

Alt text

Alt text

Cookie的限制

cookie 在性质上是绑定在特定的域名下的。当设定了一个 cookie 后,再给创建它的域名发送请求时,都会包含这个 cookie。这个限制确保了储存在 cookie 中的信息只能让批准的接受者访问,而无法被其他域访问。

  • cookie不可跨域

    Cookie遵循同源政策,每个cookie都会绑定单一的域名,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

session

除了可以将用户信息通过 Cookie 存储在用户浏览器中,也可以利用 Session 存储在服务器端,存储在服务器端的信息更加安全。

Session 可以存储在服务器上的文件、数据库或者内存中。也可以将 Session 存储在 Redis 这种内存型数据库中,效率会更高。

使用 Session 维护用户登录状态的过程如下:

  • 用户进行登录时,用户提交包含用户名和密码的表单,放入 HTTP 请求报文中;
  • 服务器验证该用户名和密码,如果正确则把用户信息存储到 Redis 中,它在 Redis 中的 Key 称为 Session ID;
  • 服务器返回的响应报文的 Set-Cookie 首部字段包含了这个 Session ID,客户端收到响应报文之后将该 Cookie 值存入浏览器中;
  • 客户端之后对同一个服务器进行请求时会包含该 Cookie 值,服务器收到之后提取出 Session ID,从 Redis 中取出用户信息,继续之前的业务操作。

应该注意 Session ID 的安全性问题,不能让它被恶意攻击者轻易获取,那么就不能产生一个容易被猜到的 Session ID 值。此外,还需要经常重新生成 Session ID。在对安全性要求极高的场景下,例如转账等操作,除了使用 Session 管理用户状态之外,还需要对用户进行重新验证,比如重新输入密码,或者使用短信验证码等方式。

Cookie 与 Session 选择

  • 存储值类型不同: Cookie 只能存储 ASCII 码字符串,想要设置其他类型的数据,需要将其转换成字符串,而 Session 则可以存储任何类型的数据,因此在考虑 数据复杂性 时首选Session;

  • 安全性: Cookie 存储在浏览器中,容易被恶意查看。如果非要将一些隐私数据存在 Cookie 中,可以将 Cookie 值进行加密,然后在服务器进行解密;

  • 对于大型网站,如果用户所有的信息都存储在 Session 中,那么开销是非常大的,因此不建议将所有的用户信息都存储到 Session 中。

    JSON Web Tokens(令牌)

    上面这种模式的问题在于,扩展性(scaling)不好。单机当然没有问题,如果是服务器集群,或者是跨域的服务导向架构,就要求 session 数据共享,每台服务器都能够读取 session。

    举例来说,A 网站和 B 网站是同一家公司的关联服务。现在要求,用户只要在其中一个网站登录,再访问另一个网站就会自动登录,请问怎么实现?

    一种解决方案是 session 数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。另外,持久层万一挂了,就会单点失败。

    另一种方案是服务器索性不保存 session 数据了,所有数据都保存在客户端,每次请求都发回服务器。JWT 就是这种方案的一个代表。

    引用:www.ruanyifeng.com/blog/2018/0…

Web 存储机制(Web Storage)

目的: 克服由 cookie 带来的一些限制,当数据需要被严格控制在客户端上时,无须持续地将数据发回服务器。

目标:

  • 提供一种在 cookie 之外存储会话数据的途径;
  • 提供一种存储大量可以跨会话存在的数据的机制。

构造函数Storage

方法:

  • clear():删除所有值;Firefox 中没有实现 。
  • getItem(name):根据指定的名字 name 获取对应的值。
  • key(index) :获得 index 位置处的值的名字。
  • removeItem(name) :删除由 name 指定的名值对儿。
  • setItem(name, value) :为指定的 name 设置一个对应的值。

sessionStorage

sessionStorage对象是Storage的一个实例

  1. 存储某个会话的数据,该数据只保持到浏览器关闭。
  2. sessionStorage中的数据可以跨越页面刷新而存在
  3. 如果浏览器支持,浏览器崩溃并重启之后依然可用(Firefox 和 WebKit 都支持,IE 则不行)。

localStorage

localStorage对象是Storage的一个实例

  1. localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。
  2. 与globalStorage不同,不能给localStorage指定任何访问规则。
  3. 要访问同一个 localStorage 对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上。(所谓同源策略)
  4. localStorage 无法通过设置失效时间来自动失效。

限制

  • 对于 localStorage 而言,大多数桌面浏览器会设置每个来源 5MB 的限制。Chrome 和 Safari 对每 个来源的限制是 2.5MB。而 iOS 版 Safari 和 Android 版 WebKit 的限制也是 2.5MB。
  • 对 sessionStorage 的限制也是因浏览器而异。有的浏览器对 sessionStorage 的大小没有限制, 但 Chrome、Safari、iOS 版 Safari 和 Android 版 WebKit 都有限制,也都是 2.5MB。IE8+和 Opera 对 sessionStorage 的限制是 5MB。

IndexedDB

。。。