🔥从购物车到登录状态:Web存储技术的全面解析🔥

109 阅读6分钟

引言

想象这样的场景:当你在电商网站精心挑选了几件商品加入购物车,突然接到一个紧急电话需要立即处理。匆忙关闭浏览器时,你是否担心过这些挑选好的商品会全部消失? 令人欣慰的是,几小时后当你再次打开网站,发现购物车里的商品依然安静地等待着你的归来。这种"记忆犹新"的体验背后,正是现代Web存储技术的魔法在发挥作用。

然而,这种看似简单的功能实现却面临着技术上的根本性挑战。由于HTTP协议本质上是无状态的,就像金鱼只有7秒记忆一般,服务器默认会"忘记"每个请求之间的关联信息。这意味着当用户添加商品到购物车后刷新页面,服务器很可能已经"不记得"这个操作——购物车会恢复成空白状态。

为了跨越这个技术鸿沟,开发者们创造了多种Web存储解决方案。这些技术不仅能记住用户的购物车内容,还能保存个性化设置、表单填写进度等各类状态信息。更重要的是,它们能确保即使用户关闭浏览器后再访问,这些数据依然能够完美重现,为用户打造连续、一致的浏览体验。在这篇文章中,我们将深入解析这些Web存储技术。

Cookie

Cookie,饼干嘛,它很小,其本质上是一小段文本信息(通常不超过4KB),由服务器发送到用户浏览器并保存在本地,浏览器每次向服务器发起请求时都会自动携带 Cookie。主要用于在无状态的 HTTP 协议下维持用户状态。

Cookie可设置过期时间(会话 Cookie 或持久 Cookie)

Cookie的最核心用途就是用来做用户身份认证

  • 服务器在用户登录后下发包含 session ID 的 Cookie,后续请求自动携带该 ID 来识别用户。
  • 或者用来记录个性化的存储,比如你用的什么主题,语言,地区所在啊等等
  • 还可以用来临时记录你的购物车的状态

接下来我们来利用html+js写一段逻辑,只有浏览器携带cookie,才能实现登录状态:

首先我们先来写服务器端:

// node 后端
// node 内置的核心模块
// js在命令行运行
// js有两种模块化方案
// require node 早期的模块化commonJS
// import es6 更先进的模块化方案
// old 老版本写法 
// node 受欢迎  中小项目开发
// 端口 对应的是某个服务
// 3306 mysql 80 web 服务 进程(资源) 线程(执行)
// 1234 8080 占用端口
// domin (localhost) -> ip地址 (127.0.0.1)->对应某台设备->port 设备上的某个服务(进程)
// 一台设备上可以有很多端口使用,有多个http服务
// 不要使用一些特殊端口
const http = require('http');
const fs = require('fs');  // file system
const path = require('path'); // 路径模块

const server = http.createServer((req, res) => {

    if (req.method == 'GET' && (req.url == '/' || req.url == '/index.html')) {
        console.log(__dirname,
            path.join(__dirname, 'public', 'index.html')
        );

        fs.readFile(path.join(__dirname, 'public', 'index.html'),
            // 回调函数 异步 callback
            (err, content) => { 
                if (err) {
                    res.writeHead(500); // 5XX 代表服务器错误
                    res.end('Server error');
                    return;
                }
                // 请求头
                res.writeHead(200, { 'Content-Type': 'text/html' })
                res.end(content)
            })
    }   // 如果访问的地址是'localhost:xxxx/'或者'localhost:xxxx/index.html,就返回这个文件'
-----------------------------------------------------------------------------------------------  
    if (req.method == 'POST' && req.url == '/login') {
        // 用户名和密码的校验
        // 写入响应头
        res.writeHead(200, {
            // 服务器端设置
            'Set-Cookie': 'username = admin',

            'Content-Type': 'application/json'
        })
        res.end(
            JSON.stringify({
                success: true,
                msg: '登陆成功'
            })

        );
    }

    if (req.method == 'GET' && req.url == '/check-login') {
        if (req.headers.cookie) {
            res.writeHead(200, {
                'Content-Type': 'application/json'
            })
            res.end(JSON.stringify({
                loggedIn: true,
                username: 'admin'
            }));
        } else {
            res.end(JSON.stringify({
                loggedIn: false,
                username: ''
            }));
        }

    }


})

server.listen(8080);

我们这里浅浅地写了一个服务器,横线的上方都是准备工作,下方才是实现登录的逻辑:

如果我们访问了/login路径,服务器就会给客户端发送一个cookie:'username = admin',当然通过登录后是需要校验的,这就是下面/check-login的作用,如果有cookie,就返回一个状态{ loggedIn: true, username: 'admin' },没有就返回相反的状态。

之后我们在前端进行校验:

document.addEventListener('DOMContentLoaded', async () => {
    // 验证是否登录?
    try {
        const response = await fetch('/check-login')
        const data = await response.json();
          // 利用显示不同元素,来展现是否登录的效果
        if (data.loggedIn) {
            document.getElementById('loginSection').style.display = 'none';
            document.getElementById('welcomeSection').style.display = 'block';
            document.getElementById('userDisplay').textContent = data.username;
        } else {
            document.getElementById('loginSection').style.display = 'block';
            document.getElementById('welcomeSection').style.display = 'none';
        }

    } catch (err) {
            console.log(err)
    }
})

OK,这样cookie的介绍就完成了。

其他存储方式

localStorage

localStorage 是 HTML5 提供的 客户端存储 API,用于在浏览器中持久化存储键值对数据。

特性说明
存储大小5~10MB(不同浏览器上限不同)
存储类型仅支持 字符串键值对(需手动序列化对象)
数据持久性关闭浏览器后 不会清除,需手动删除或通过代码清除
作用域同源策略(相同协议+域名+端口共享数据)
API 同步/异步同步操作(可能阻塞主线程,大量数据时需谨慎)
是否自动发送到服务器❌ 不会像 Cookie 那样随 HTTP 请求自动发送

一般都储存一些不需要频繁更新的数据。

具有localStorage.setItem(key,value)localStorage.getItem(key),两个API,第一个可以设置要存储的值,第二个可以通过key访问所存储的值。

Session

在 Web 开发中,Session(会话) 是一种服务器端技术,用于 跟踪用户的状态。由于 HTTP 协议是无状态的,Session 机制能让服务器在多个请求之间记住用户信息(如登录状态、购物车数据等)。

特性说明
存储位置服务器端(如内存、数据库、Redis)
生命周期用户会话期间有效(默认关闭浏览器后失效,也可设置过期时间)
安全性比 Cookie 更安全(敏感数据不直接存储在客户端)
依赖关系通常依赖 Cookie(存储 Session ID)或 URL 重写
适用场景登录状态管理、敏感数据存储(如用户权限、临时凭证)

为什么说通常依赖cookie呢?这是因为客户端首次访问时:

  • 服务器为该用户创建唯一 Session ID(如 sess_abc123)。
  • 服务器存储 Session 数据(如 { user_id: 123, is_logged_in: true })。
  • 通过 Set-Cookie 将 Session ID 发给浏览器(默认 Cookie 名为 PHPSESSIDJSESSIONID 等)。

之后每次请求链接,服务器都会根据cookie所携带的Session ID来辨认身份,查找对应的数据。

为什么说Session在浏览器关闭后失效?

Session的数据都会存储在Session-Cookie中,而会话级别的Cookie在浏览器关闭的时候就会进行销毁,这时Session也就失效了。

在关闭标签页时,浏览器不会销毁Session Cookie,但某些设置,如Chrome的退出时清理Cookie,会使得退出标签页的时候一同清理Cookie。

总结

Cookie、localStorage和Session是Web开发中三大核心存储方案。Cookie(≤4KB)由服务器通过Set-Cookie设置,自动随请求发送,适用于身份验证(如Session ID)。localStorage(5-10MB)持久存储客户端数据(需手动序列化),用于偏好设置或离线缓存。Session依赖服务端存储(如Redis),通过Session ID(通常存于Cookie)关联用户状态,适合敏感数据(如登录态)。三者协同实现无状态HTTP下的用户体验连续性,需根据安全性、生命周期和存储需求选择。