您现在的位置是:网站首页 > cookie操作文章详情
cookie操作
陈川
【
JavaScript
】
22765人已围观
10085字
什么是Cookie
Cookie是存储在用户计算机上的小型文本文件,用于在浏览器和服务器之间传递信息。它们通常用于会话管理、个性化设置和跟踪用户行为。每个Cookie由名称、值、属性(如过期时间、域名、路径等)组成,大小限制一般为4KB左右。
// 一个简单的Cookie示例
document.cookie = "username=JohnDoe; expires=Thu, 18 Dec 2025 12:00:00 UTC; path=/";
Cookie的基本操作
设置Cookie
在JavaScript中,可以通过直接赋值给document.cookie来设置Cookie。需要注意的是,这种方式不会覆盖现有Cookie,而是添加新的Cookie。
function setCookie(name, value, days) {
const date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
const expires = "expires=" + date.toUTCString();
document.cookie = `${name}=${value};${expires};path=/`;
}
// 使用示例
setCookie("theme", "dark", 30);
setCookie("language", "zh-CN", 365);
读取Cookie
读取所有Cookie可以通过document.cookie属性,它会返回当前域名下所有Cookie的字符串。
function getCookie(name) {
const cookieName = `${name}=`;
const cookies = document.cookie.split(';');
for(let i = 0; i < cookies.length; i++) {
let cookie = cookies[i].trim();
if (cookie.indexOf(cookieName) === 0) {
return cookie.substring(cookieName.length, cookie.length);
}
}
return "";
}
// 使用示例
const theme = getCookie("theme");
console.log(theme); // 输出"dark"(如果设置了该Cookie)
删除Cookie
删除Cookie的原理是将过期时间设置为过去的时间。
function deleteCookie(name) {
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
}
// 使用示例
deleteCookie("theme");
Cookie属性详解
expires/max-age
控制Cookie的生存时间。expires指定具体过期时间,max-age指定存活秒数。
// 使用expires
document.cookie = "session=abc123; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/";
// 使用max-age(单位:秒)
document.cookie = "preferences=dark_mode; max-age=31536000; path=/"; // 一年后过期
path
指定Cookie可用的路径。默认为设置Cookie的页面路径。
// 只在/admin路径下可用
document.cookie = "admin_token=xyz789; path=/admin";
domain
指定Cookie可用的域名。默认为当前域名,不能设置为其他域名。
// 对example.com及其所有子域名可用
document.cookie = "user_id=123; domain=.example.com; path=/";
secure
标记Cookie只能通过HTTPS协议传输。
document.cookie = "secure_token=abc; secure; path=/";
HttpOnly
防止JavaScript访问Cookie,增强安全性(只能在服务器端设置)。
// 服务器端设置示例(Node.js Express)
res.cookie('sessionID', '12345', { httpOnly: true });
SameSite
控制Cookie是否随跨站请求发送,防止CSRF攻击。
document.cookie = "csrftoken=abcdef; SameSite=Strict; path=/";
document.cookie = "sessionid=ghijk; SameSite=Lax; path=/";
实际应用场景
用户偏好设置
存储用户选择的主题、语言等偏好设置。
// 保存主题偏好
function saveThemePreference(theme) {
setCookie("user_theme", theme, 365);
applyTheme(theme);
}
// 应用主题
function applyTheme(theme) {
document.body.className = theme;
}
// 初始化时检查Cookie
window.addEventListener('DOMContentLoaded', () => {
const savedTheme = getCookie("user_theme") || "light";
applyTheme(savedTheme);
});
购物车功能
在用户关闭浏览器前保留购物车内容。
// 添加商品到购物车
function addToCart(productId, quantity) {
const cart = getCart();
cart[productId] = (cart[productId] || 0) + quantity;
saveCart(cart);
}
// 获取购物车
function getCart() {
const cartCookie = getCookie("shopping_cart");
return cartCookie ? JSON.parse(cartCookie) : {};
}
// 保存购物车
function saveCart(cart) {
setCookie("shopping_cart", JSON.stringify(cart), 7); // 保存7天
}
用户认证
存储认证令牌(通常配合HttpOnly更安全)。
// 登录成功后设置认证令牌
function handleLoginSuccess(authToken) {
setCookie("auth_token", authToken, 1); // 1天后过期
redirectToDashboard();
}
// 检查登录状态
function checkAuth() {
const token = getCookie("auth_token");
if (!token) {
redirectToLogin();
}
}
高级技巧
处理特殊字符
Cookie值中如果包含特殊字符(如分号、逗号、空格等),需要进行编码。
function setCookieSafe(name, value, days) {
const encodedValue = encodeURIComponent(value);
setCookie(name, encodedValue, days);
}
function getCookieSafe(name) {
const value = getCookie(name);
return value ? decodeURIComponent(value) : "";
}
// 使用示例
setCookieSafe("user_data", JSON.stringify({name: "John; Doe", age: 30}), 30);
const userData = JSON.parse(getCookieSafe("user_data"));
批量操作Cookie
同时设置或获取多个Cookie。
// 批量设置Cookie
function setMultipleCookies(cookies, days) {
cookies.forEach(([name, value]) => {
setCookie(name, value, days);
});
}
// 批量获取Cookie
function getMultipleCookies(names) {
return names.reduce((result, name) => {
result[name] = getCookie(name);
return result;
}, {});
}
Cookie大小限制
处理Cookie大小超过限制的情况。
function setLargeCookie(name, value, days, chunkSize = 2000) {
// 删除现有Cookie
deleteCookie(name);
// 如果值不大,正常设置
if (value.length <= chunkSize) {
setCookie(name, value, days);
return;
}
// 大Cookie分块存储
const chunks = Math.ceil(value.length / chunkSize);
for (let i = 0; i < chunks; i++) {
const chunk = value.substr(i * chunkSize, chunkSize);
setCookie(`${name}_${i}`, chunk, days);
}
setCookie(`${name}_chunks`, chunks, days);
}
function getLargeCookie(name) {
const chunks = parseInt(getCookie(`${name}_chunks`)) || 1;
if (chunks === 1) return getCookie(name);
let value = '';
for (let i = 0; i < chunks; i++) {
value += getCookie(`${name}_${i}`);
}
return value;
}
安全注意事项
敏感信息存储
避免在Cookie中存储敏感信息,如密码、信用卡号等。
// 不安全的做法
setCookie("password", "123456", 30); // 绝对不要这样做!
// 相对安全的做法
setCookie("session_id", generateSecureRandomToken(), 1);
CSRF防护
使用SameSite属性和CSRF令牌增强安全性。
// 生成CSRF令牌
function generateCSRFToken() {
const token = crypto.randomUUID(); // 或其他随机生成方法
setCookie("csrf_token", token, 1, true); // HttpOnly最好在服务器设置
return token;
}
// 验证CSRF令牌
function validateCSRFToken(token) {
const storedToken = getCookie("csrf_token");
return token && storedToken && token === storedToken;
}
定期清理
定期清理不再需要的Cookie。
// 清理过期Cookie
function cleanUpCookies() {
const cookies = document.cookie.split(';');
cookies.forEach(cookie => {
const [name] = cookie.split('=').map(s => s.trim());
if (name.startsWith('temp_')) {
deleteCookie(name);
}
});
}
// 页面加载时执行清理
window.addEventListener('load', cleanUpCookies);
性能优化
减少Cookie数量
合并多个小Cookie为一个JSON格式的大Cookie。
// 合并用户偏好设置
const userPreferences = {
theme: "dark",
fontSize: "medium",
notifications: true
};
setCookieSafe("user_prefs", JSON.stringify(userPreferences), 365);
// 读取时
const prefs = JSON.parse(getCookieSafe("user_prefs"));
使用子域名分担
将静态资源使用的Cookie放在子域名下,减少主域名Cookie的大小。
// 静态资源子域名
document.cookie = "static_cookie=value; domain=static.example.com; path=/";
无Cookie域名
对于静态资源,使用完全独立的无Cookie域名。
// 图片、CSS、JS等使用无Cookie域名
// <img src="https://cdn.example.com/image.jpg">
浏览器兼容性处理
检测Cookie是否可用
function areCookiesEnabled() {
try {
const testKey = 'test_cookie';
document.cookie = `${testKey}=1`;
const enabled = document.cookie.indexOf(testKey) !== -1;
deleteCookie(testKey);
return enabled;
} catch (e) {
return false;
}
}
if (!areCookiesEnabled()) {
showCookieWarning();
}
处理第三方Cookie限制
现代浏览器对第三方Cookie的限制越来越严格。
// 检查是否支持SameSite=None
function supportsSameSiteNone() {
try {
document.cookie = "test=1; SameSite=None";
return document.cookie.includes("test=1");
} catch (e) {
return false;
}
}
替代方案比较
localStorage vs sessionStorage vs Cookie
// localStorage示例 - 持久化存储,同源可用
localStorage.setItem("user_settings", JSON.stringify(settings));
const settings = JSON.parse(localStorage.getItem("user_settings"));
// sessionStorage示例 - 会话级存储,标签页关闭后清除
sessionStorage.setItem("temp_data", data);
const tempData = sessionStorage.getItem("temp_data");
// 选择依据:
// 1. 需要服务器访问?使用Cookie
// 2. 需要持久化且只在客户端使用?localStorage
// 3. 临时数据?sessionStorage
IndexedDB
对于更复杂、更大的客户端数据存储需求。
// IndexedDB示例
const request = indexedDB.open("userDatabase", 1);
request.onupgradeneeded = (event) => {
const db = event.target.result;
const store = db.createObjectStore("preferences", { keyPath: "id" });
};
request.onsuccess = (event) => {
const db = event.target.result;
const tx = db.transaction("preferences", "readwrite");
const store = tx.objectStore("preferences");
store.put({ id: "theme", value: "dark" });
};
调试技巧
查看和编辑Cookie
现代浏览器开发者工具都提供了Cookie查看和编辑功能。
// 在控制台快速查看所有Cookie
console.log(document.cookie);
// 以对象形式查看
console.log(Object.fromEntries(document.cookie.split('; ').map(c => c.split('='))));
模拟不同Cookie场景
// 临时修改Cookie进行测试
function mockCookie(name, value) {
const original = getCookie(name);
setCookie(name, value, 1);
return {
restore: () => {
if (original) {
setCookie(name, original, 1);
} else {
deleteCookie(name);
}
}
};
}
// 使用示例
const mock = mockCookie("auth_token", "test_token");
// 执行测试...
mock.restore();
服务器端协作
与Node.js Express配合
const express = require('express');
const cookieParser = require('cookie-parser');
const app = express();
app.use(cookieParser());
app.get('/set-cookie', (req, res) => {
res.cookie('server_cookie', 'value_from_server', {
maxAge: 900000,
httpOnly: true,
secure: true,
sameSite: 'strict'
});
res.send('Cookie set');
});
app.get('/get-cookie', (req, res) => {
const cookieValue = req.cookies.server_cookie;
res.send(`Cookie value: ${cookieValue}`);
});
与PHP配合
<?php
// 设置Cookie
setcookie("php_cookie", "value_from_php", time() + 3600, "/", "", false, true);
// 读取Cookie
$cookieValue = $_COOKIE['php_cookie'] ?? 'default';
echo "Cookie value: $cookieValue";
?>
未来发展趋势
Cookie的替代技术
随着隐私保护要求的提高,新技术正在出现。
// 使用Storage Access API处理第三方存储访问
document.hasStorageAccess().then(hasAccess => {
if (!hasAccess) {
return document.requestStorageAccess();
}
}).then(() => {
// 现在可以访问存储
}).catch(err => {
// 处理拒绝
});
// 使用Partitioned Cookie
document.cookie = "__Host-partitioned=value; Secure; Path=/; Partitioned;";