Javascript 本地存储:cookie、sessionStorage、localStorage、indexedDB

JavaScript本地缓存的方法我们主要讲述以下四种:

  • cookie
  • sessionStorage
  • localStorage
  • indexedDB

cookie

Cookie,类型为「小型文本文件」,指某些网站为了辨别用户身份而储存在用户本地终端上的数据。

一般不超过 4KB 的小型文本数据,它由一个名称(Name)、一个值(Value)和其它几个用于控制 cookie有效期、安全性、使用范围的可选属性组成。

// 设置`username='jack'的cookie`
document.cookie = 'username=jack';

cookie在每次请求中都会被发送,如果不使用 HTTPS并对其加密,其保存的信息很容易被窃取,导致安全风险。

⚡️ JavaScript Cookie 详解

特点

  1. 不设置过期时间(cookie保存在内存里):
    则cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了
    这种生命期为浏览会话期的cookie被称为会话cookie

  2. 设置了过期时间(浏览器就会把cookie保存到硬盘上):
    则cookie生命周期为只在设置的cookie过期时间之前一直有效
    关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
    存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。

.

缺点

  • cookie 存放数据大小为4K左右, 且有个数限制(各浏览器不同),一般不能超过20个。不能储存大数据且不易读取。
    localStoragesessionStorage 能存放5M或者更大。
  • http请求 时需要发送到服务端,增加了请求的数据量

.

用法

创建或修改cookie:

document.cookie = "key=value; expires=date; path=path; domain=domain; secure";
  • 名称和值 key=value:要设置的cookie的名称和值。
  • 有效期 expires=date:可选,cookie的过期日期。如果不设置,则cookie在浏览器关闭时过期。
  • 路径 path=path:可选,指定哪些路径下的页面可以访问该cookie。默认为设置cookie的页面所在的路径。
  • domain=domain:可选,指定哪些域名下的页面可以访问该cookie。默认为设置cookie的页面的域名。
  • HTTPS传输 secure:可选,如果设置了该属性,则只能通过HTTPS协议来传输cookie。

例如,设置一个名为 username、值为 猫老板、过期时间为 7天 后的 cookie:

document.cookie = "username=猫老板; expires=" + new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toUTCString();

.

⚡️ Set-Cookie 响应头

字段名类别描述示例
Name常见Cookie的名称UserID
Value常见Cookie的值123456
Expires有效期Cookie的过期日期/时间Expires=Wed, 21 Oct 2023 07:28:00 GMT
Max-Age有效期定义Cookie生命周期的秒数(如果设置,将覆盖Expires)Max-Age=86400 (1天)
Domain作用域限制哪些可以接收CookieDomain=example.com
Path作用域限制哪些路径下的页面可以接收CookiePath=/users
Secure安全性限制Cookie只能通过HTTPS传输Secure
HttpOnly安全性限制JavaScript访问(即无法通过document.cookie访问)HttpOnly
SameSite安全性控制Cookie的跨站策略SameSite=LaxSameSite=StrictSameSite=None

Web Storage

Web Storage 是一种在客户端存储数据的 Web API,它提供了两种在浏览器中存储数据的方式:localStoragesessionStorage

这两种存储方式都使得数据可以在用户的浏览器会话中持久保存,但与传统的 cookies 相比,它们提供了更大的存储容量(通常可以达到数兆字节)和更好的性能。

localStorage

localStorage 的生命周期是永久的,关闭页面或浏览器 localStorage 中的数据也不会消失。localStorage 除非主动删除数据,否则数据永远不会消失。

特点

  • 生命周期:持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的
  • 存储的信息在同一域中是共享的
  • 当本页操作(新增、修改、删除)了localStorage的时候,本页面不会触发storage事件,但是别的页面会触发storage事件。
  • 大小:5M(跟浏览器厂商有关系)
  • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
  • 受同源策略的限制

缺点

  • 无法像Cookie一样设置过期时间
  • 浏览器的大小不统一,并且在 IE8 以上的 IE 版本才支持 localStorage 这个属性。
  • 只能存入字符串,无法直接存对象,这个在对我们日常比较常见的JSON对象类型需要一些转换。
  • 在浏览器的隐私模式下面是不可读取的。
  • 本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡。
  • 不能被爬虫抓取到。

用法

// 设置
localStorage.setItem('username','猫老板');

// 获取
localStorage.getItem('username');

// 获取键名
localStorage.key(0) //获取第一个键名

// 删除
localStorage.removeItem('username');

// 清除所有存储
localStorage.clear()

.

sessionStorage

sessionStorage和 localStorage使用方法基本一致,唯一不同的是生命周期。
sessionStorage 的生命周期是仅在当前会话下有效,关闭页面或浏览器 sessionStorage 中的数据会被销毁清空。

sessionStorage 引入了一个“浏览器窗口”的概念,sessionStorage 是在同源的窗口中始终存在的数据。只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。同时独立的打开同一个窗口同一个页面,sessionStorage 也是不一样的(不同浏览器、同一个页面也是不共享的)。

localStorage 与 sessionStorage的封装(可设置过期时间)


indexedDB

indexedDB是一种低级API,用于客户端存储大量结构化数据(包括, 文件/ blobs)。该API使用索引来实现对该数据的高性能搜索

虽然 Web Storage对于存储较少量的数据很有用,但对于存储更大量的结构化数据来说,这种方法不太有用。IndexedDB提供了一个解决方案

优点

  • 储存量理论上没有上限
  • 所有操作都是异步的,相比 LocalStorage 同步操作性能更高,尤其是数据量较大时
  • 原生支持储存JS的对象
  • 是个正经的数据库,意味着数据库能干的事它都能干

缺点

  • 操作非常繁琐
  • 本身有一定门槛

用法

  1. 打开数据库并且开始一个事务

  2. 创建一个 object store

  3. 构建一个请求来执行一些数据库操作,像增加或提取数据等。

  4. 通过监听正确类型的 DOM 事件以等待操作完成。

  5. 在操作结果上进行一些操作(可以在 request对象中找到)

以下是一个简单的 IndexedDB 用法示例,该示例展示了如何打开一个数据库,创建一个对象存储(object store),并添加、检索和删除数据。

const dbName = 'myDatabase';  // 数据库名称
const dbVersion = 1;  // 数据库版本
  
// 打开数据库  
const request = indexedDB.open(dbName, dbVersion);  
  
request.onerror = function(event) {  
  console.error("Database error: " + event.target.errorCode);  
};  
  
request.onsuccess = function(event) {  
  // 获取数据库对象  
  const db = event.target.result;  
  
  // 创建一个对象存储(如果不存在)  
  if (!db.objectStoreNames.contains('myObjectStore')) {  
    db.createObjectStore('myObjectStore', { keyPath: 'id' });  
  }  
  
  // 示例:添加数据  
  const transaction = db.transaction(['myObjectStore'], 'readwrite');  
  const store = transaction.objectStore('myObjectStore');  
  store.put({ id: 1, name: 'Alice', age: 25 });  
  store.put({ id: 2, name: 'Bob', age: 30 });  
  
  transaction.oncomplete = function(event) {  
    console.log('Data added successfully');  
  
    // 检索数据  
    const tx = db.transaction(['myObjectStore'], 'readonly');  
    const store = tx.objectStore('myObjectStore');  
  
    // 获取所有记录  
    const getAllRequest = store.getAll();  
    getAllRequest.onsuccess = function(event) {  
      console.log('Retrieved data:', event.target.result);  
    };  
  
    // 获取指定记录  
    const getRequest = store.get(1);  
    getRequest.onsuccess = function(event) {  
      console.log('Retrieved specific data:', event.target.result);  
    };  
  
    // 删除数据  
    const deleteRequest = store.delete(2);  
    deleteRequest.onsuccess = function(event) {  
      console.log('Data deleted successfully');  
    };  
  };  
  
  transaction.onerror = function(event) {  
    console.error('Transaction error: ' + event.target.errorCode);  
  };  
};  
  
request.onupgradeneeded = function(event) {  
  // 当数据库版本发生变化时,这个事件会被触发  
  // 在这里可以修改或删除现有的对象存储,或者创建新的对象存储  
  const db = event.target.result;  
  // ...  
};

三方库(Godb.js)

关于使用indexdb的使用会比较繁琐,大家可以通过使用 Godb.js 库进行缓存,最大化的降低操作难度

安装:npm install godb

操作非常简单,增、删、改、查各只需要一行代码:

import GoDB from 'godb';

const testDB = new GoDB('testDB');
const user = testDB.table('user');

const data = {
  name: 'luke',
  age: 22
};

user.add(data) // 增
  .then(luke => user.get(luke.id)) // 查,等价于 user.get({ id: luke.id })
  .then(luke => user.put({ ...luke, age: 23 })) // 改
  .then(luke => user.delete(luke.id)); // 删

⚡️ 区别

特性cookiesessionStoragelocalStorageindexedDB
数据存储位置客户端浏览器,随HTTP请求发送到服务器客户端浏览器,当前会话期间有效客户端浏览器,永久存储客户端浏览器,持久化存储
数据大小限制约4KB(具体取决于浏览器)5MB(或更大,取决于浏览器)5MB(或更大,取决于浏览器)几乎没有限制
数据生命周期可设置过期时间,过期后自动删除会话结束(浏览器关闭或标签页关闭)永久存储,除非手动删除永久存储,除非手动删除
数据类型字符串键值对,任何数据类型(对象会被转换为字符串)键值对,任何数据类型(对象会被转换为字符串)复杂的结构化数据,支持索引
访问方式服务器端和客户端均可访问仅客户端JavaScript可访问仅客户端JavaScript可访问仅客户端JavaScript可访问
安全性安全性较低,可通过HTTP请求发送安全性较高,不会随HTTP请求发送安全性较高,不会随HTTP请求发送安全性较高,不会随HTTP请求发送
同步/异步同步(但不建议在服务器端同步使用)同步同步异步
搜索功能不支持不支持不支持支持
跨域共享可通过服务器设置跨域访问不支持跨域共享不支持跨域共享不支持跨域共享(但可通过其他机制如postMessage实现)
应用场景标记用户与跟踪用户行为的情况敏感账号一次性登录适合长期保存在本地的数据(令牌)存储大量数据的情况、在线文档(富文本编辑器)保存编辑历史的情况

单点登录 SSO

在同域下的客户端/服务端认证系统中,通过客户端携带凭证,维持一段时间内的登录状态。

但当我们业务线越来越多,就会有更多业务系统分散到不同域名下,就需要「一次登录,全线通用」的能力,叫做「单点登录」。

  1. 主域名相同的单点登录:

    如果业务系统都在同一主域名下,比如 wenku.baidu.comtieba.baidu.com,就好办了。

    可以直接把 cookie domain 设置为主域名 .baidu.com,百度也就是这么干的。

    在这里插入图片描述
    .

  2. 主域名不同的单点登录:

    比如滴滴公司,同时拥有 didichuxing.comxiaojukeji.comdidiglobal.com 等域名,这三种 cookie 是完全绕不开的。

    这要能实现「一次登录,全线通用」,才是真正的单点登录

    这种场景下,我们需要独立的认证服务,通常被称为 SSO。

以下是关键步骤:

  1. 用户进入 A 系统,若没有登录凭证(ticket:如session ID或token),A 系统将用户重定向到 SSO 服务器进行身份验证

  2. SSO 没登录过,也就没有 SSO 系统下没有凭证,则用户需要输入账号密码进行登录

  3. SSO 账号密码验证成功,通过接口返回做两件事:

    • 保存登录凭证,记录用户在 SSO 登录状态
    • SSO服务器会发送一个授权令牌(如JWT)或票据(ticket)给客户端,并可能设置一个cookie在用户的浏览器中,以便后续识别用户的登录状态。
      .
  4. 客户端拿到 ticket,保存起来,并带着 ticket 请求系统 A 接口

  5. A 系统校验 ticket,成功后正常处理业务请求

  6. 此时用户第一次进入 B 系统,若没有登录凭证(ticket),B 系统将用户重定向到 SSO 服务器进行身份验证

  7. 由于用户之前在 SSO 服务器上登录过(有登录凭证),并且会话仍然有效,不用再次登录,只需要生成一个新的 ticket(或者重用已有的 ticket ),并将其发送给客户端。

  8. 客户端拿到 ticket,保存起来,带着请求系统 B 接口

  9. B 系统校验 ticket,成功后正常处理业务请求

这个流程描述了用户如何通过 SSO 系统登录并在多个系统(A 系统和 B 系统)之间无缝切换,而无需在每个系统上都输入用户名和密码。

这是单点登录系统的主要优势之一,提高了用户体验并降低了管理多个账户和密码的复杂性。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫老板的豆

你的鼓励将是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值