您现在的位置是:网站首页 > cookie操作文章详情

cookie操作

什么是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;";

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步