引言:为什么你的网站需要记住用户?
你有没有想过 —— 为什么淘宝能记住你的购物车?为什么 B 站能自动登录你的账号?🤔 这些看似简单的功能背后,藏着 Web 开发的核心难题:无状态的 HTTP 协议如何记住用户身份?
答案就在今天的主角 ——Cookie身上!作为前端存储的 "元老级选手",Cookie 用小小的文本数据解决了 Web 身份认证的大问题。本文将通过一个可直接运行的实战项目,带你从 0 到 1 掌握 Cookie 的工作原理与登录状态管理技巧~
一、Cookie 核心原理:3 分钟看懂 "小饼干" 的大作用
1. 什么是 Cookie?
Cookie 是浏览器存储的小型文本数据(通常≤4KB),就像网站给用户发的 "电子门票"🎫。每次访问网站时,浏览器会自动带上这张 "门票",让服务器认出你是谁。
2. 为什么需要 Cookie?
HTTP 协议是无状态的 —— 这意味着服务器默认记不住你:
-
第一次访问和第 1000 次访问,服务器收到的请求完全一样
-
没有 Cookie 时,每次登录都要重新输入账号密码(想想都崩溃!)
Cookie 的出现打破了这个限制:通过在请求头中携带身份信息,让服务器能 "记住" 用户状态。
3. Cookie 的工作流程
用户登录 → 服务器生成Cookie(Set-Cookie响应头) → 浏览器存储Cookie →
下次请求自动携带Cookie → 服务器验证身份 → 返回对应内容
二、实战项目:用 Cookie 搭建登录系统(附完整代码)
项目结构速览
📁 项目文件夹
├─ 📄 index.html (前端页面)
├─ 📄 style.css (样式文件)
├─ 📄 script.js (前端交互逻辑)
└─ 📄 server.js (Node后端服务)
1. 前端页面:登录表单与状态展示(index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cookie登录演示</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<h1>🍪 Cookie登录系统</h1>
<div id="app">
<!-- 登录表单区域 -->
<section id="loginSection" style="display: none;">
<form id="loginForm">
<input type="text" placeholder="用户名" id="username" required />
<input type="password" placeholder="密码" id="password" required />
<button type="submit">登录</button>
</form>
</section>
<!-- 登录成功区域 -->
<section id="welcomeSection" style="display: none;">
<p>欢迎回来,<span id="userDisplay"></span> 👋</p>
<button id="logoutBtn">退出登录</button>
</section>
</div>
<script src="./script.js"></script>
</body>
</html>
✨ 关键细节:
- 用两个
section分别存放 "登录表单" 和 "欢迎信息" - 初始状态都隐藏,通过 JS 根据登录状态动态切换显示
2. 前端交互:处理登录与状态检查(script.js)
// 监听登录表单提交
const loginForm = document.getElementById('loginForm');
loginForm.addEventListener('submit', async (event) => {
// 阻止表单默认提交行为(避免页面刷新)
event.preventDefault();
// 获取用户输入
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value.trim();
try {
// 发送登录请求到后端
const response = await fetch('/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username, password })
});
const data = await response.json();
if (data.success) {
alert('登录成功!即将刷新页面 🔄');
window.location.reload(); // 刷新页面触发状态检查
}
} catch (err) {
console.log('登录出错了:', err);
}
});
// 页面加载时检查登录状态
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);
}
});
🚀 核心逻辑:
- 登录时通过
fetch发送 POST 请求,后端验证后设置 Cookie - 页面加载时调用
/check-login接口,后端通过 Cookie 判断登录状态 - 动态切换 DOM 显示,实现 "未登录→显示表单"、"已登录→显示欢迎信息"
3. 后端服务:设置 Cookie 与验证身份(server.js)
// 导入Node核心模块
const http = require('http');
const fs = require('fs');
const path = require('path');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 1. 处理静态文件请求(HTML/CSS/JS)
if (req.method === 'GET' && (req.url === '/' || req.url === '/index.html')) {
fs.readFile(
path.join(__dirname, 'public', 'index.html'),
(err, content) => {
if (err) {
res.writeHead(500);
res.end('Server Error');
return ;
}
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
});
}
if(req.method === 'GET'&&req.url === '/style.css'){
fs.readFile(
path.join(__dirname,'public','style.css'),
(err, content) => {
if (err) {
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200, { 'Content-Type': 'text/css' });
res.end(content);
})
}
if(req.method === 'GET'&&req.url === '/script.js'){
fs.readFile(path.join(__dirname,'public','script.js'),
(err, content) => {
if (err) {
res.writeHead(500);
res.end('Server Error');
return;
}
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.end(content);
})
}
// 2. 处理登录请求(设置Cookie)
if (req.method === 'POST' && req.url === '/login') {
// 实际开发中这里需要校验用户名密码,这里简化处理
res.writeHead(200, {
'Set-Cookie': 'user=admin; path=/; max-age=3600', // 设置Cookie(1小时过期)
'Content-Type': 'application/json'
});
res.end(JSON.stringify({
success: true,
msg: '登录成功' }));
}
// 3. 处理登录状态检查(读取Cookie)
if (req.method === 'GET' && req.url === '/check-login') {
const cookies = req.headers.cookie || '';
const isLoggedIn = cookies.includes('user=admin'); // 简单判断Cookie是否存在
res.writeHead(200, {
'Content-Type': 'application/json' });
res.end(JSON.stringify({
loggedIn: isLoggedIn,
username: isLoggedIn ? 'admin' : ''
}));
}
});
// 启动服务器(监听8080端口)
server.listen(8080, () => {
console.log('服务器已启动:http://localhost:8080 🎉');
});
🔑 关键代码解析:
Set-Cookie响应头:服务器通过它向前端设置 Cookie(path=/表示全站有效,max-age=3600表示 1 小时后过期)req.headers.cookie:后端读取前端发送的 Cookie,判断用户是否登录- 路由设计:用
method + url区分不同请求(静态资源 / 登录 / 状态检查)
三、Cookie 实战注意事项(避坑指南)
-
安全性问题 🔒
- 不要存储敏感信息(如密码),Cookie 会明文传输
- 重要场景可加
HttpOnly属性(防止 JS 读取,避免 XSS 攻击)
-
大小限制 📏
- 单条 Cookie≤4KB,过多会增加请求体积,影响性能
-
自动携带特性 🚚
- 每次请求都会自动带上 Cookie,需合理设置
path和domain限制范围
- 每次请求都会自动带上 Cookie,需合理设置
-
过期策略 ⏰
max-age:以秒为单位的有效期(如 3600=1 小时)expires:指定具体过期时间(UTC 格式)- 不设置则为 "会话 Cookie",关闭浏览器后失效
总结:Cookie 在现代 Web 中的定位
Cookie 虽小,却是 Web 身份认证的基石!它用简单的 "请求 - 响应" 模式,解决了 HTTP 无状态的核心痛点。本文通过一个完整项目,演示了从登录表单提交、服务器设置 Cookie,到前端状态检查的全流程。
实际上,除了 Cookie,前端存储还有localStorage、sessionStorage、indexedDB等方案,但 Cookie 在登录状态管理领域仍不可替代 🌟。