前言

网页刷新的时候数据会被清空,这时候就需要用到存储技术。前端本地存储的方式有三种,分别是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请求

URL是否被允许通信解释
http://www.abc.com/a.js、http://www.abc.com/b.js可以同协议、同域名、同端口
http://www.abc.com/a.js、https://www.abc.com/b.js不可以不同协议
http://www.abc.com/a.js、http://www.xxx.com/b.js不可以不同域名
http://www.abc.com/a.js、http://www.abc.com:8080/b.js不可以不同端口

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也是不能相互访问的。

(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不会被爬虫爬取到数据

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐