cookie操作的完整封装方案

Cookie是浏览器提供的一种本地存储机制,属于BOM(Browser Object Model)的一部分。它允许网站在用户计算机上存储少量数据(通常不超过4KB),并在后续请求中将这些数据发送回服务器。

Cookie的特性

  1. 域名绑定:Cookie与特定域名绑定,只能由创建它的域名访问
  2. 有效期:可以设置过期时间,可以是会话级(浏览器关闭即删除)或持久性
  3. 路径限制:可以限制Cookie只在网站的特定路径下可用
  4. 安全标志:Secure标志确保Cookie只在HTTPS连接下传输
  5. HttpOnly:防止JavaScript访问,增强安全性防止XSS攻击

二、原生Cookie操作的问题

原生JavaScript通过document.cookie操作Cookie存在以下问题:

  1. 接口不友好,需要手动拼接字符串
  2. 读取时需要解析整个cookie字符串
  3. 缺乏便捷的设置选项(如过期天数、路径等)
  4. 没有统一的错误处理机制

三、完整的Cookie封装方案

下面是一个完整的Cookie操作封装实现,解决了上述所有问题:

javascript 复制代码
const Cookie = {
  /**
   * 设置Cookie
   * @param {string} name - Cookie名称
   * @param {string} value - Cookie值
   * @param {Object} [options] - 配置选项
   * @param {number} [options.expires] - 过期天数
   * @param {string} [options.path] - 路径,默认为'/'
   * @param {string} [options.domain] - 域名
   * @param {boolean} [options.secure] - 是否仅HTTPS
   * @param {boolean} [options.httpOnly] - 是否禁止JS访问
   */
  set(name, value, options = {}) {
    let cookieStr = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
    
    if (options.expires) {
      const date = new Date();
      date.setTime(date.getTime() + options.expires * 24 * 60 * 60 * 1000);
      cookieStr += `; expires=${date.toUTCString()}`;
    }
    
    cookieStr += `; path=${options.path || '/'}`;
    
    if (options.domain) {
      cookieStr += `; domain=${options.domain}`;
    }
    
    if (options.secure) {
      cookieStr += '; secure';
    }
    
    if (options.httpOnly) {
      cookieStr += '; HttpOnly';
    }
    
    document.cookie = cookieStr;
  },
  
  /**
   * 获取Cookie
   * @param {string} name - 要获取的Cookie名称
   * @return {string|null} - Cookie值,不存在时返回null
   */
  get(name) {
    const cookies = document.cookie.split('; ');
    for (const cookie of cookies) {
      const [cookieName, cookieValue] = cookie.split('=');
      if (decodeURIComponent(cookieName) === name) {
        return decodeURIComponent(cookieValue);
      }
    }
    return null;
  },
  
  /**
   * 删除Cookie
   * @param {string} name - 要删除的Cookie名称
   * @param {string} [path] - 路径,默认为'/'
   * @param {string} [domain] - 域名
   */
  remove(name, path = '/', domain) {
    this.set(name, '', {
      expires: -1,
      path,
      domain
    });
  },
  
  /**
   * 检查Cookie是否存在
   * @param {string} name - 要检查的Cookie名称
   * @return {boolean} - 是否存在
   */
  has(name) {
    return this.get(name) !== null;
  },
  
  /**
   * 获取所有Cookie名称
   * @return {Array<string>} - Cookie名称数组
   */
  keys() {
    return document.cookie.split('; ').map(cookie => {
      return decodeURIComponent(cookie.split('=')[0]);
    });
  }
};

四、封装方案的使用示例

1. 设置Cookie

javascript 复制代码
// 设置会话Cookie
Cookie.set('username', 'john_doe');

// 设置7天后过期的Cookie
Cookie.set('preferences', 'dark_mode', { expires: 7 });

// 设置安全Cookie
Cookie.set('auth_token', 'abc123', { secure: true, httpOnly: true });

2. 获取Cookie

javascript 复制代码
const username = Cookie.get('username');
console.log(username); // 输出: john_doe

3. 删除Cookie

javascript 复制代码
Cookie.remove('preferences');

4. 检查Cookie是否存在

javascript 复制代码
if (Cookie.has('session_id')) {
  console.log('用户已登录');
}

5. 获取所有Cookie名称

javascript 复制代码
const allCookies = Cookie.keys();
console.log(allCookies); // 输出: ['username', 'auth_token']

五、封装方案的进阶优化

1. 添加JSON支持

javascript 复制代码
// 在set方法中添加
if (typeof value === 'object') {
  value = JSON.stringify(value);
}

// 在get方法中添加
try {
  const parsed = JSON.parse(decodedValue);
  return parsed;
} catch (e) {
  return decodedValue;
}

2. 添加默认配置

javascript 复制代码
const Cookie = {
  _defaultOptions: {
    path: '/',
    expires: 30, // 默认30天过期
    secure: window.location.protocol === 'https:'
  },
  
  set(name, value, options = {}) {
    const mergedOptions = { ...this._defaultOptions, ...options };
    // 其余代码不变
  }
  // ...
};

3. 添加大小限制检查

javascript 复制代码
set(name, value, options = {}) {
  const cookieStr = `${name}=${value}`;
  if (cookieStr.length > 4096) {
    console.warn(`Cookie ${name} exceeds size limit of 4KB`);
    return false;
  }
  // 其余设置代码
}

六、浏览器兼容性考虑

  1. 所有现代浏览器都支持基本的Cookie操作
  2. IE浏览器对Cookie大小限制更严格(每个Cookie不超过4095字节,每个域名不超过50个Cookie)
  3. 移动端浏览器对Cookie的支持可能有限,特别是在WebView中
  4. 第三方Cookie可能被浏览器阻止(如Safari的智能防跟踪功能)

七、安全最佳实践

  1. 敏感数据不要存储在Cookie中
  2. 始终对Cookie值进行编码/解码
  3. 为敏感Cookie设置Secure和HttpOnly标志
  4. 考虑使用SameSite属性防止CSRF攻击
  5. 定期轮换认证令牌

结语

本文提供的Cookie封装方案解决了原生API的诸多不便,提供了更友好、更安全的接口。在实际项目中,可以根据需要进一步扩展功能,如添加TypeScript类型定义、增加更详细的错误处理等。对于现代Web应用,也可以考虑结合localStorage、sessionStorage和IndexedDB等存储方案,根据数据特性选择最合适的存储方式。