Cookie 操作 #

什么是 Cookie? #

Cookie 是存储在浏览器中的小型文本数据,用于在客户端和服务器之间传递状态信息。

text
┌─────────────────────────────────────────────────────────────┐
│                      Cookie 工作原理                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│   浏览器 ◄──────────────────────────────────► 服务器         │
│     │                                           │            │
│     │  1. 首次请求                               │            │
│     │ ─────────────────────────────────────────► │            │
│     │                                           │            │
│     │  2. 响应 + Set-Cookie 头                   │            │
│     │ ◄───────────────────────────────────────── │            │
│     │                                           │            │
│     │  3. 存储 Cookie                           │            │
│     │                                           │            │
│     │  4. 后续请求自动携带 Cookie                 │            │
│     │ ─────────────────────────────────────────► │            │
│                                                              │
└─────────────────────────────────────────────────────────────┘
text
┌─────────────────────────────────────────────────────────────┐
│                     Cookie 特点                              │
├─────────────────────────────────────────────────────────────┤
│  大小限制:单个 Cookie 最大 4KB                               │
│  数量限制:每个域名最多 20-50 个 Cookie                        │
│  自动发送:每次 HTTP 请求自动携带                              │
│  过期时间:可设置过期时间                                      │
│  作用域:可设置域名和路径限制                                  │
│  安全性:支持 HttpOnly、Secure、SameSite                      │
└─────────────────────────────────────────────────────────────┘

基础函数 #

setCookie(name, value, days) #

设置 Cookie。

javascript
export const setCookie = (name, value, days) => {
    let expires = '';
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = '; expires=' + date.toUTCString();
    }
    document.cookie = name + '=' + value + expires + '; path=/';
};

使用示例 #

javascript
import { setCookie } from './utils/cookie';

setCookie('token', 'abc123xyz', 7);
setCookie('user', 'John', 30);
setCookie('preference', 'dark', 365);
setCookie('session', 'xyz789');

设置选项 #

javascript
const setCookieAdvanced = (name, value, options = {}) => {
    const {
        days = 0,
        path = '/',
        domain = '',
        secure = false,
        sameSite = 'Lax'
    } = options;
    
    let cookie = `${name}=${encodeURIComponent(value)}`;
    
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
        cookie += `; expires=${date.toUTCString()}`;
    }
    
    cookie += `; path=${path}`;
    
    if (domain) {
        cookie += `; domain=${domain}`;
    }
    
    if (secure) {
        cookie += '; Secure';
    }
    
    cookie += `; SameSite=${sameSite}`;
    
    document.cookie = cookie;
};

setCookieAdvanced('token', 'abc123', {
    days: 7,
    secure: true,
    sameSite: 'Strict'
});

getCookie(name) #

获取 Cookie 值。

javascript
export const getCookie = (name) => {
    const reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
    const match = document.cookie.match(reg);
    return match ? match[2] : null;
};

使用示例 #

javascript
import { getCookie } from './utils/cookie';

const token = getCookie('token');
const user = getCookie('user');

if (token) {
    console.log('用户已登录');
} else {
    console.log('用户未登录');
}
javascript
const getAllCookies = () => {
    const cookies = {};
    document.cookie.split(';').forEach(cookie => {
        const [name, value] = cookie.trim().split('=');
        if (name) {
            cookies[name] = decodeURIComponent(value || '');
        }
    });
    return cookies;
};

getAllCookies();

deleteCookie(name) #

删除 Cookie。

javascript
export const deleteCookie = (name) => {
    document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
};

使用示例 #

javascript
import { deleteCookie } from './utils/cookie';

deleteCookie('token');
deleteCookie('user');
deleteCookie('session');
javascript
const deleteCookieWithDomain = (name, domain, path = '/') => {
    document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}; domain=${domain}`;
};

deleteCookieWithDomain('token', '.example.com');

1. Expires / Max-Age #

javascript
const setCookieWithExpires = (name, value, expiresDate) => {
    document.cookie = `${name}=${value}; expires=${expiresDate.toUTCString()}; path=/`;
};

const setCookieWithMaxAge = (name, value, maxAge) => {
    document.cookie = `${name}=${value}; max-age=${maxAge}; path=/`;
};

const oneHourLater = new Date(Date.now() + 60 * 60 * 1000);
setCookieWithExpires('session', 'abc', oneHourLater);

setCookieWithMaxAge('session', 'abc', 3600);

2. Path #

javascript
setCookie('app1', 'value1', 1);
setCookie('app2', 'value2', 1);

document.cookie = 'global=value; path=/';
document.cookie = 'admin=value; path=/admin';

3. Domain #

javascript
document.cookie = 'main=value; path=/; domain=example.com';
document.cookie = 'sub=value; path=/; domain=sub.example.com';
document.cookie = 'wildcard=value; path=/; domain=.example.com';

4. Secure #

javascript
const setSecureCookie = (name, value, days) => {
    let cookie = `${name}=${value}; path=/`;
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
        cookie += `; expires=${date.toUTCString()}`;
    }
    cookie += '; Secure';
    document.cookie = cookie;
};

setSecureCookie('secureToken', 'abc123', 7);

5. HttpOnly #

javascript
// 注意:HttpOnly 只能通过服务器设置
// HTTP 响应头示例:
// Set-Cookie: token=abc123; HttpOnly; Secure; SameSite=Strict

6. SameSite #

javascript
const setCookieWithSameSite = (name, value, days, sameSite = 'Lax') => {
    let cookie = `${name}=${value}; path=/`;
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
        cookie += `; expires=${date.toUTCString()}`;
    }
    cookie += `; SameSite=${sameSite}`;
    document.cookie = cookie;
};

setCookieWithSameSite('token', 'abc', 7, 'Strict');
setCookieWithSameSite('session', 'xyz', 1, 'Lax');
setCookieWithSameSite('tracking', '123', 30, 'None');

SameSite 值对比 #

描述 适用场景
Strict 完全禁止第三方 Cookie 敏感操作
Lax 允许 GET 请求携带 大多数场景(默认)
None 允许跨站发送 需要 Secure 配合

实际应用场景 #

1. 用户登录状态管理 #

javascript
import { setCookie, getCookie, deleteCookie } from './utils/cookie';

class AuthManager {
    constructor() {
        this.tokenKey = 'auth_token';
        this.userKey = 'user_info';
    }
    
    login(token, user, rememberMe = false) {
        const days = rememberMe ? 30 : 1;
        setCookie(this.tokenKey, token, days);
        setCookie(this.userKey, JSON.stringify(user), days);
    }
    
    logout() {
        deleteCookie(this.tokenKey);
        deleteCookie(this.userKey);
    }
    
    isLoggedIn() {
        return !!getCookie(this.tokenKey);
    }
    
    getToken() {
        return getCookie(this.tokenKey);
    }
    
    getUser() {
        const userStr = getCookie(this.userKey);
        return userStr ? JSON.parse(userStr) : null;
    }
}

const auth = new AuthManager();
auth.login('abc123', { id: 1, name: 'John' }, true);

2. 用户偏好设置 #

javascript
import { setCookie, getCookie } from './utils/cookie';

class PreferenceManager {
    constructor() {
        this.key = 'user_preferences';
    }
    
    get() {
        const prefStr = getCookie(this.key);
        return prefStr ? JSON.parse(prefStr) : this.getDefaults();
    }
    
    set(preferences) {
        const current = this.get();
        const updated = { ...current, ...preferences };
        setCookie(this.key, JSON.stringify(updated), 365);
    }
    
    getDefaults() {
        return {
            theme: 'light',
            language: 'zh-CN',
            fontSize: 'medium',
            notifications: true
        };
    }
    
    reset() {
        setCookie(this.key, JSON.stringify(this.getDefaults()), 365);
    }
}

const prefs = new PreferenceManager();
prefs.set({ theme: 'dark' });

3. 多语言切换 #

javascript
import { setCookie, getCookie } from './utils/cookie';

class LanguageManager {
    constructor() {
        this.key = 'language';
        this.defaultLang = 'zh-CN';
        this.supportedLangs = ['zh-CN', 'en-US', 'ja-JP'];
    }
    
    get() {
        const saved = getCookie(this.key);
        if (saved && this.supportedLangs.includes(saved)) {
            return saved;
        }
        return this.detectBrowserLanguage() || this.defaultLang;
    }
    
    set(lang) {
        if (this.supportedLangs.includes(lang)) {
            setCookie(this.key, lang, 365);
            window.location.reload();
        }
    }
    
    detectBrowserLanguage() {
        const browserLang = navigator.language || navigator.userLanguage;
        return this.supportedLangs.find(lang => browserLang.startsWith(lang.split('-')[0]));
    }
}

const langManager = new LanguageManager();
langManager.set('en-US');

4. A/B 测试 #

javascript
import { setCookie, getCookie } from './utils/cookie';

class ABTestManager {
    constructor() {
        this.key = 'ab_test';
    }
    
    getVariant(testName, variants = ['A', 'B']) {
        const tests = this.getAll();
        if (tests[testName]) {
            return tests[testName];
        }
        
        const variant = variants[Math.floor(Math.random() * variants.length)];
        tests[testName] = variant;
        setCookie(this.key, JSON.stringify(tests), 30);
        
        return variant;
    }
    
    getAll() {
        const str = getCookie(this.key);
        return str ? JSON.parse(str) : {};
    }
}

const abTest = new ABTestManager();
const variant = abTest.getVariant('button_color', ['red', 'blue', 'green']);
console.log(`用户分组: ${variant}`);

安全最佳实践 #

1. 敏感数据处理 #

javascript
const setSecureCookie = (name, value, options = {}) => {
    const {
        days = 1,
        secure = true,
        sameSite = 'Strict'
    } = options;
    
    let cookie = `${name}=${encodeURIComponent(value)}; path=/`;
    
    if (days) {
        const date = new Date();
        date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
        cookie += `; expires=${date.toUTCString()}`;
    }
    
    if (secure && location.protocol === 'https:') {
        cookie += '; Secure';
    }
    
    cookie += `; SameSite=${sameSite}`;
    
    document.cookie = cookie;
};
javascript
import md5 from './md5';

const setEncryptedCookie = (name, value, secret, days) => {
    const encrypted = btoa(value);
    const signature = md5(encrypted + secret);
    setCookie(name, `${encrypted}.${signature}`, days);
};

const getDecryptedCookie = (name, secret) => {
    const cookieValue = getCookie(name);
    if (!cookieValue) return null;
    
    const [encrypted, signature] = cookieValue.split('.');
    const expectedSignature = md5(encrypted + secret);
    
    if (signature !== expectedSignature) {
        console.error('Cookie 签名验证失败');
        return null;
    }
    
    return atob(encrypted);
};

3. 防止 XSS 攻击 #

javascript
const safeSetCookie = (name, value, days) => {
    const safeName = encodeURIComponent(name);
    const safeValue = encodeURIComponent(value);
    setCookie(safeName, safeValue, days);
};

const safeGetCookie = (name) => {
    try {
        const value = getCookie(encodeURIComponent(name));
        return value ? decodeURIComponent(value) : null;
    } catch (e) {
        console.error('Cookie 读取错误:', e);
        return null;
    }
};
特性 Cookie localStorage sessionStorage
大小限制 4KB 5MB 5MB
过期时间 可设置 永久 会话结束
HTTP 请求 自动携带 不携带 不携带
跨标签页 共享 共享 隔离
安全属性 丰富 一般 一般

下一步 #

现在你已经掌握了 Cookie 操作,接下来学习 日期时间处理,了解日期格式化和时间计算!

最后更新:2026-04-04