浏览器有三种方式可以存储数据,分别是Cookie
localStorage
sessionStorage
。其中localStorage
sessionStorage
是新的功能,但并不是用来代替Cookie
的。
Cookie的最初目的是用于服务器和客户端之间的数据交流。很大程度上,是给服务器端使用的。
比如用户登录后,服务器需要给客户端一个标识,下次客户端访问时带上这个标识,于是服务器可以识别出这个已登录的用户。Cookie甚至可以设置成httpOnly,只能在服务器端被读取,客户端使用js无法访问。
因此,cookie总是会随着http请求一起发送到服务器端。而且cookie有设置过期时间、关闭网页自动删除等功能。自然的,浏览器上多个tab页之间共享cookie。
由于cookie会作为http请求的一部分发送到服务器,那么肯定不能太大,太大势必会影响性能。
另外,cookie中包含用户标识,自动作为http请求的一部分发送到服务器,也导致了一个常见的漏洞,CSRF攻击。
cookie设计之初,大概没打算让客户端过多的使用cookie。毕竟客户端用的数据,无端的发送到服务器上,浪费带宽、性能,怎么看都奇怪。于是就有了localStorage
sessionStorage
。
localStorage很显然是只给客户端自己用的。只保存在客户端本地,不会随http请求自动发送到服务器,所以可以更大。
localStorage不能设置过期时间,虽然过期时间的应用场合并不多,但在某些特殊场合需要使用时,就很麻烦。解决办法是,在存储值时同时存储过期时间,读取时判断是否过期,过期则删除并返回空。有类库支持这个功能:localstorage-slim
。
最重要的是,关闭页面不能自动清空localStorage,这导致不能把敏感的登录数据(如JWT token)保存到这里。否则会出现关闭页面后,其它使用者也可打开浏览器盗取登录标识(如JWT token)。
那么使用sessionStorage不就好了?本来是没错,但sessionStorage不能够跨浏览器tab页签。
用法各方面基本和localStorage一样。区别主要有两个,一是tab页关闭,sessionStorage自动清空;二是各tab页签不共享sessionStorage。
通过链接打开新窗口,Chrome会复制一份sessionStorage(但不共享),Firefox则不会。
如此一来,sessionStorage就变成了鸡肋,不同tab页签不共享session不符合大部分用户的使用习惯。
但细细一想,这么做也非常合理。sessionStorage其实就是给单页应用使用的,和vue的状态类似,浏览器的tab页签之间不共享,页面关闭就消失。区别在于vue的状态刷新页面后就消失了,而sessionStorage页面刷新还是保留的。