前端本地存储的方式有三种,分别是cookie、localStorage、sessionStorage。在前端面试过程中,经常会被问及这些存储技术和区别,优缺点,但是很少有人真正理解这些存储技术的具体介绍。笔者以为在学习过程中,首先要明白是什么学懂是什么为什么怎么样,然后再去比较这三者会比较好一点,有一种逻辑性,而不是一上来就背诵一些面经。本文会先整理这三者的介绍,下一篇文章会详细整理这三者的区别和应用场景。
一、cookie
1.1 cookie是什么?
http是一种无状态协议,就是一种不保存状态的协议,一个服务器不清楚是不是同一个浏览器在访问它。cookie的出现是为了解决前一种技术token的缺陷。为了解决http无状态的特点,会在请求中插入token,然后发送请求,告诉服务器,但是这种方式容易出错,所以cookie就出现了。
http协议中的cookie包括web cookie和浏览器 cookie,是服务器发送到web浏览器的一小块数据,保存在浏览器的一小段文本信息,浏览器进行存储并且下次发送请求的时候携带上cookie。浏览器每次向服务器发送请求都会携带这段信息。用于判断了两个请求是否来自于同一个浏览器。
cookie是一种浏览器管理状态的一个文件,它有name、value,Domain、path等等。
1.2 cookie原理
第一次访问网站,浏览器会发送一个请求,服务器响应这个请求,会将cookie放进响应请求中。
第二次访问网站,浏览器发送的请求带有cookie,服务器会辨别这个用户的身份,相应的服务器也可以修改cookie。
用一个流程图表示(如下,推荐画图工具processon!)
1.3 cookie不可跨域请求
知识点补充
Q1:什么是跨域?
A1:在浏览器环境下,跨域是指一个域下文档或脚本去请求另一个域下的资源。
Q2:什么是域?
A2:协议+域名+端口
正常情况下,如果我们通过ajax去请求另一个域的资源是不可行的,违背浏览器的同源策略,浏览器默认阻拦这种行为。
Q3:什么是同源策略?
A3:同源策略SOP(Same Origin Policy),Netscape公司1995年提出并且引入浏览器。浏览器最核心的安全策略。缺少安全策略浏览器容易受到XSS、CSFR等等的攻击。同源就是协议+域名+端口相同。
Q4:同源可以获得浏览器什么支持?
A4:获取cookie、localStorage;获取DOM和js对象;发送ajax请求
cookie不可以跨域请求
javascript:document.cookie='myname=laihuamin;path=/;domain=.baidu.com';
javascript:document.cookie='myname=huaminlai;path=/;domain=.google.com';
打开控制台,输入上面两个语句
解析:cookie能设置上去的只有domain是baidu.com的cookie绑定到了域名上面。所以证明了cookie不可以跨域请求,不能在不同的域名下用。
1.4 cookie的属性
(1)Name
cookie的名字,一个域名下绑定的cookie的name不能相同。如果是相同的name则会被覆盖。
(2)value
每个cookie拥有的属性,表示cookie的值。
由于cookie规定是名称/值是不允许包含分号,逗号,空格的,所以为了不给用户到来麻烦,考虑服务器的兼容性,任何存储cookie的数据都应该被URL编码。
(3)domain
cookie的域名。cookie绑定的域名,如果没有设置,自动绑定当前执行语句的的域。同一个域名下的二级域名也是不可以交换cookie的。
(4)path
path是默认属性’/',匹配web路由
路径设置/blog的时候,也会给/blog绑定cookie
//默认 www.baidu.com //blog路径 www.baidu.com/blog
(5)Expires
expires是cookie的有效期。一般浏览器的cookie是默认存储的,关闭浏览器结束会话,cookie就会被删除。
如果想要cookie续存一段时间,可以通过设置expires有效期。
expires现在被Max-Age取代:Max-Age,是以秒为单位的,Max-Age为正数时,cookie会在Max-Age秒之后,被删除;当Max-Age为负数时,表示的是临时储存,不会生出cookie文件,只会存在浏览器内存中,且只会在打开的浏览器窗口或者子窗口有效,一旦浏览器关闭,cookie就会消失;当Max-Age为0时,删除cookie,因为cookie机制本身没有设置删除cookie,失效的cookie会被浏览器自动从内存中删除,所以,它实现的就是让cookie失效。
(6)secure
安全。http无状态无加密,不安全协议容易被攻击挟持。比如你在浏览页面的时候是不是会有小广告出来。这个secure属性为true的时候,这个时候的cookie只会在https和ssl等安全协议下传输。不能对cookie加密,绝对安全保证做不到。
(7)httpOnly
安全的 Cookie 需要经过 HTTPS 协议通过加密的方式发送到服务器。即使是安全的,也不应该将敏感信息存储在cookie 中,因为它们本质上是不安全的,并且此标志不能提供真正的保护。
作用:①会话 Cookie 中缺少 HttpOnly 属性会导致攻击者可以通过程序(JS脚本、Applet等)获取到用户的 Cookie 信息,造成用户 Cookie 信息泄露,增加攻击者的跨站脚本攻击威胁。
②HttpOnly 是微软对 Cookie 做的扩展,该值指定 Cookie 是否可通过客户端脚本访问。
③如果在 Cookie 中没有设置 HttpOnly 属性为 true,可能导致 Cookie 被窃取。窃取的 Cookie 可以包含标识站点用户的敏感信息,如 ASP.NET 会话 ID 或 Forms 身份验证票证,攻击者可以重播窃取的 Cookie,以便伪装成用户或获取敏感信息,进行跨站脚本攻击等。
1.5 js操作cookie
//document.cookie //读取浏览器的cookie console.log(document.cookie) //写入cookie document.cookie = 'myname = ;path = /;domain = ';
1.6 服务端设置cookie
服务端通过setCookie来设置cookie,设置多个就多写几个setCookie。请求携带cookie传送给后端。
1.7 cookie的应用
(1)会话管理
登录验证、购物车、游戏得分或者其他服务器应该记住的状态。
登录验证:用户在第一次登录某个网站时,要输入用户名密码,如果觉得很麻烦,下次登录时不想输入了,那么就在第一次登录时将登录信息存放在 cookie 中。下次登录时我们就可以直接获取 cookie 中的用户名密码来进行登录。浏览器将信息保存在cookie是加密,但是不是绝对安全,也有造成不安全的信息泄漏的可能。
购物车:类似于购物车性质的功能,第一次用户将某些商品放入购物车了,但是临时有事,将电脑关闭了,下次再次进入此网站,我们可以通过读取 cookie 中的信息,恢复购物车中的物品。现在基本很少用,都是存储在数据库中,通过查询数据库来恢复购物车信息。
(2)个性化定制
用户的个性化定制主题,用户的偏好
(3)追踪
记录分析用户行为。Cookie曾经是客户端存储数据的唯一方式,如今改进用API。cookie每个请求都会携带会大大降低性能,尤其是对于移动数据的链接。
(4)页面传值
在实际开发中,我们往往会通过一个页面跳转到另外一个页面。后端服务器我们可以通过数据库,session 等来传递页面所需要的值。但是在浏览器端,我们可以将数据保存在 cookie 中,然后在另外页面再去获取 cookie 中的数据。cookie的数据具有时效性,注意过期日期不然会造成数据混乱。
1.8 cookie两种类型—会话cookie和永久性cookie
cookie有两种类型,分类取决于是否含有到期日期。
①一种是Session Cookies:会话cookie存储在内存,浏览器关闭cookie永久丢失。
②一种是Persistent Cookies:永久性cookie存储在磁盘,有效期到了将从磁盘中删除。
会话cookie
客户端关闭,数据删除,永久丢失。没有指定的Expires/Max-Age指令,存储在内存。
ps:Web浏览器可以让会话还原,可以让大多数会话cookie数据保持永久性,像浏览器永远没有关闭一样。
永久性cookie
客户端关闭,数据不会删除。当Expires或者Max-Age过期,才会删除数据,存储在磁盘。
1.9 cookie禁用
cookie可能被禁用,当用户非常注重隐私的时候,可以禁用浏览器的cookie功能。比如SessionID通过cookie存储在客户端,如果cookie被禁用,必然会造成Session使用的影响。
解决方法:URL重写
①servlet中涉及客户端输出页面元素的时候,在相应的请求地址外面加一层方法,response.encodeURL(‘URL’);为请求地址添加JSESSIONID的值。
②servlet跳转页面,使用response.encodeRedirectURL(‘URL’),为请求地址添加JSESSIONID的值。
1.10 总结
(1)cookie可能被禁用。当用户非常注重个人隐私的时候,浏览器cookie可以被禁用。
(2)cookie与浏览器相关。cookie是不能跨域请求的,访问同一个页面,不同浏览器之间保存的cookie也是不能相互访问的。cookie同一个浏览器的同源下是可以公用的,和是不是同一个页签没有关系。
(3)cookie可能被删除。每个cookie都是硬盘中的文件,因此可能被用户删除。
(4)cookie安全性不高。所有的cookie都是以纯文本形式记录在文件中,如果要保存加密信息,最好实现经过加密处理。
过渡
cookie可用于传递少量的数据,是一个在客户端和服务器之间来回传送文本值的内置机制,cookie只能传送很小的数据并且需要在客户端和服务器之间频繁传送时,cookie才有意义。那么如果需要在客户端保存大量的数据该怎么办呢?这时候就要用到另一种本地存储技术Web storage,web storage本地存储可以在客户端保存大量的数据。
HTML5提供了2种API:sessionStorage会话存储、localStorage本地存储
cookie完全是服务端可以操作的数据,sessionStorage和localStorage完全是浏览器端可以操作的数据。
二、sessionStorage
2.1 什么是sessionStorage
2.2 sessionStorage属性
sessionStorage的属性有Key和Value,保存了大量的数据。
2.3 如何使用sessionStorage
提出问题:存储是对象,为什么value对应的是[‘object Object’]呢?
解决问题:
sessionStorage.setItem('tg',JSON.stringify(person))
提出问题:尝试获取数据,取出的是string类型
解决问题:
const changeResult = JSON.parse(sessionStorage.getItem('tg'))
总结:通过转成字符串的形式存储,取出的时候转成对象,就能正常的存储和读取。
2.4 失效时间
sessionStorage的生命周期仅在当前会话有效。sessionStorage引入了“浏览器窗口的概念”。sessionStorage在同源窗口中始终存在数据,只要浏览器窗口没有关闭,刷新或者重新进入页面数据依然存在。关闭浏览器窗口后数据会被删除。再次独立打开同一个窗口同一个页面,sessionStorage也是不一样。
2.5 存储的位置
sessionStorage都保存在客户端,一般不与服务器进行通信交互。
2.6 存储的大小
sessionStorage存储数据大小一般是5MB
2.7 存储内容的类型
sessionStorage只能存储字符串类型,对于复杂对象可以使用ECMAScript对象的stringify和parse处理。
2.8 获取方式
//sessionStorage window.sessionStorage
2.9 sessionStorage的应用
敏感账号一次性登录
三、localStorage
3.1 什么是localStorage
3.2 localStorage的属性
localStorage的属性有Key和Value,保存了大量的数据。
3.3 失效时间
localStorage的生命周期是永久的,关闭页面或者浏览器之后localStorage中的数据也不会消失。localStorage删除数据要手动删除,否则数据永远不会消失。
3.4 存储的位置
localStorage都保存在客户端,一般不与服务器进行通信交互。
3.5 存储的大小
localStorage存储数据大小一般是5MB
3.6 存储内容的类型
localStorage只能存储字符串类型,对于复杂对象可以使用ECMAScript对象的stringify和parse处理。
3.7 获取方式
//localStorage window.localStorage
3.8 localStorage的应用
常用于长期登录、判断是否已登录、适合长期保存在本地的数据。
3.9 手写会过期的localStorage
惰性删除、定时删除
惰性删除:某个键值过期后,该键值不会被马上删除,而是等到下次被使用的时候,才会被检查到过期,此时才能得到删除。
缺点:惰性删除已经实现可过期的localStorage缓存,但是也有明显的缺点。如果一个key一直没有被用到,就不会被及时检查,即使过期了也一直存在localStorage。
var lsc = (function (self) { var prefix = 'one_more_lsc_' /** * 增加一个键值对数据 * @param key 键 * @param val 值 * @param expires 过期时间,单位为秒 */ self.set = function (key, val, expires) { key = prefix + key; val = JSON.stringify({'val': val, 'expires': new Date().getTime() + expires * 1000}); localStorage.setItem(key, val); }; /** * 读取对应键的值数据 * @param key 键 * @returns {null|*} 对应键的值 */ self.get = function (key) { key = prefix + key; var val = localStorage.getItem(key); if (!val) { return null; } val = JSON.parse(val); if (val.expires < new Date().getTime()) { localStorage.removeItem(key); return null; } return val.val; }; return self; }(lsc || {}));
定时删除:每隔一段时间执行一次删除操作,并通过限制删除操作执行的次数和频率,来减少删除操作对CPU的长期占用。另一方面定时删除也有效的减少了因惰性删除带来的对localStorage空间的浪费。
每隔一秒执行一次定时删除,操作如下:
①随机测试20个设置了过期时间的key
②删除所有发现的已过期的key
③若删除的key超过5个则重复步骤1,直到重复500次
var lsc = (function (self) { var prefix = 'one_more_lsc_' var list = []; //初始化list self.init = function () { var keys = Object.keys(localStorage); var reg = new RegExp('^' + prefix); var temp = []; //遍历所有localStorage中的所有key for (var i = 0; i < keys.length; i++) { //找出可过期缓存的key if (reg.test(keys[i])) { temp.push(keys[i]); } } list = temp; }; self.init(); self.check = function () { if (!list || list.length == 0) { return; } var checkCount = 0; while (checkCount < 500) { var expireCount = 0; //随机测试20个设置了过期时间的key for (var i = 0; i < 20; i++) { if (list.length == 0) { break; } var index = Math.floor(Math.random() * list.length); var key = list[index]; var val = localStorage.getItem(list[index]); //从list中删除被惰性删除的key if (!val) { list.splice(index, 1); expireCount++; continue; } val = JSON.parse(val); //删除所有发现的已过期的key if (val.expires < new Date().getTime()) { list.splice(index, 1); localStorage.removeItem(key); expireCount++; } } //若删除的key不超过5个则跳出循环 if (expireCount <= 5 || list.length == 0) { break; } checkCount++; } } //每隔一秒执行一次定时删除 window.setInterval(self.check, 1000); return self; }(lsc || {}));
3.10 localStorage的限制
(1)IE8以上版本才支持localStorage这个属性
(2)目前主流浏览器中都会把localStorage的值类型限定为string类型,这个对我们日常比较常见的JSON对象类型需要一些转换
(3)localStorage在浏览器的隐私模式下不可读取
(4)localStorage本质上是对字符串的读取。如果读取内容多的话会消耗内存空间,导致页面卡。
(5)localStorage不会被爬虫爬取到数据
- sessionStorage localStorage cookiesessionstorage localstorage cookie sessionstorage localstorage router cookie sessionstorage localstorage session cookie sessionstorage localstorage cookies sessionstorage localstorage cookies vue 前端sessionstorage localstorage cookies 前端sessionstorage localstorage cookie sessionstorage localstorage sessionstorage localstorage网站 拷贝 前端sessionstorage缓存localstorage