跟我一起吃下”Cookie“这块小饼干

340 阅读6分钟

Cookie 是一种存储在用户浏览器中的小段数据,通常由服务器生成并通过 HTTP 响应发送给客户端。为了控制 Cookie 的行为和安全性,Cookie 提供了一系列属性。以下是 Cookie 的常见属性及其含义:


1. Name=Value

  • 描述:这是 Cookie 的核心部分,表示键值对。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123;
    

2. Expires 或 Max-Age

  • 描述:用于设置 Cookie 的过期时间。

    • Expires:指定一个具体的过期日期和时间(UTC 时间)。
    • Max-Age:指定 Cookie 的有效时长(以秒为单位)。优先级高于 Expires
  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; Expires=Wed, 21 Oct 2025 07:28:00 GMT;
    Set-Cookie: sessionId=abc123; Max-Age=3600; // 有效期为 1 小时
    
  • 默认值:如果不设置 Expires 或 Max-Age,Cookie 会在浏览器关闭后失效(称为会话 Cookie)。


3. Domain

  • 描述:指定 Cookie 的作用域,即哪些域名可以访问该 Cookie。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; Domain=example.com;
    
  • 注意事项

    • 如果未设置 Domain,Cookie 默认仅对当前页面的域名生效。
    • 子域名可以通过设置 Domain 来共享 Cookie,例如 Domain=.example.com 可以让 sub.example.com 和 example.com 共享 Cookie。

4. Path

  • 描述:指定 Cookie 的路径作用域,限制 Cookie 在哪个路径下可用。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; Path=/admin;
    
  • 默认值:如果未设置 Path,Cookie 默认对当前页面的路径及其子路径生效。

  • 注意事项Path=/ 表示整个域名下的所有路径都可以访问该 Cookie。


5. Secure

  • 描述:标记 Cookie 只能通过 HTTPS 协议传输。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; Secure;
    
  • 用途:防止 Cookie 被窃听或篡改,适用于敏感数据(如认证信息)。


6. HttpOnly

  • 描述:标记 Cookie 不能被 JavaScript 访问,从而降低 XSS 攻击的风险。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; HttpOnly;
    
  • 用途:保护敏感 Cookie 不被恶意脚本获取。


7. SameSite

  • 描述:控制 Cookie 是否可以随跨站请求一起发送。

  • 取值

    • Strict:Cookie 仅在第一方上下文中发送,不允许跨站请求携带。
    • Lax:允许部分跨站请求携带 Cookie(如 GET 请求)。
    • None:允许所有跨站请求携带 Cookie,但必须同时设置 Secure 属性。
  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; SameSite=Strict;
    Set-Cookie: sessionId=abc123; SameSite=None; Secure;
    
  • 用途:防止 CSRF(跨站请求伪造)攻击。


8. Priority(非标准)

  • 描述:一些浏览器支持 Priority 属性,用于设置 Cookie 的优先级(高、中、低)。

  • 示例

    http
    深色版本
    Set-Cookie: sessionId=abc123; Priority=High;
    
  • 用途:优化浏览器对 Cookie 的处理顺序。


9. 其他属性

  • SameParty(实验性):限制 Cookie 只能在同公司的一组站点之间共享。
  • Partitioned(实验性):将 Cookie 与特定的网络身份绑定,防止跨站点跟踪。

设置 Cookie 的方式

1. 通过 HTTP 响应头

服务器可以通过 Set-Cookie 响应头设置 Cookie:

http
深色版本
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; HttpOnly; Secure; Path=/; Max-Age=3600;

2. 通过 JavaScript

客户端可以通过 document.cookie 设置 Cookie:

javascript
深色版本
document.cookie = "sessionId=abc123; path=/; max-age=3600; secure; httponly";
  • 注意事项

    • HttpOnly 和 Secure 属性无法通过 JavaScript 设置。
    • 使用 JavaScript 设置 Cookie 时需要特别注意安全性。

删除 Cookie

要删除一个 Cookie,可以通过设置其 Max-Age=0Expires 为过去的某个时间来实现:

http
深色版本
Set-Cookie: sessionId=abc123; Max-Age=0;

Cookie 既可以由服务端设置,也可以由客户端(浏览器端)设置,下面分别介绍这两种设置方式及相关场景:

服务端设置 Cookie

原理

服务端在处理客户端的 HTTP 请求时,通过在响应头中添加 Set - Cookie 字段来告知浏览器设置 Cookie。浏览器接收到响应后,会根据 Set - Cookie 字段的内容来创建或更新相应的 Cookie。

示例(以 Node.js 的 http 模块为例)

const http = require('http');

const server = http.createServer((req, res) => {
    // 设置 Cookie 的名称和值
    const cookieName = 'user';
    const cookieValue = 'JohnDoe';

    // 设置 Cookie 的选项,例如有效期(以秒为单位)
    const options = {
        maxAge: 3600, // 1 小时
        path: '/', // 表示该 Cookie 对整个网站都有效
        httpOnly: true // 防止客户端脚本访问 Cookie
    };

    // 构建 Set - Cookie 头部字符串
    let cookieString = `${cookieName}=${cookieValue}`;
    if (options.maxAge) {
        cookieString += `; Max - Age=${options.maxAge}`;
    }
    if (options.path) {
        cookieString += `; Path=${options.path}`;
    }
    if (options.httpOnly) {
        cookieString += `; HttpOnly`;
    }

    // 设置响应头中的 Set - Cookie 字段
    res.setHeader('Set - Cookie', cookieString);

    // 设置响应状态码和内容类型
    res.writeHead(200, { 'Content - Type': 'text/plain' });
    res.end('Cookie has been set by server');
});

const port = 3000;
server.listen(port, () => {
    console.log(`Server running at http://localhost:${port}/`);
});

场景

  • 身份验证:服务端在用户登录成功后,会设置一个包含用户身份信息的 Cookie,用于后续请求的身份验证。
  • 会话管理:通过设置会话 ID 的 Cookie,服务端可以跟踪用户的会话状态。
  • 个性化设置:根据用户的偏好设置,服务端可以设置相应的 Cookie,以便在后续请求中提供个性化的内容。

客户端(浏览器端)设置 Cookie

原理

在浏览器环境中,可以使用 JavaScript 通过 document.cookie 属性来设置 Cookie。document.cookie 是一个字符串属性,将符合格式的 Cookie 字符串赋值给它,浏览器就会创建或更新相应的 Cookie。

示例

// 定义一个函数来设置 Cookie
function setCookie(name, value, daysToExpire, path) {
    // 创建一个日期对象,用于设置过期时间
    const expirationDate = new Date();
    // 将过期时间设置为当前时间加上指定的天数(转换为毫秒)
    expirationDate.setTime(expirationDate.getTime() + (daysToExpire * 24 * 60 * 60 * 1000));

    // 对 Cookie 的名称和值进行 URL 编码,以处理特殊字符
    const encodedName = encodeURIComponent(name);
    const encodedValue = encodeURIComponent(value);

    // 构建 Cookie 字符串,包含名称、值和过期时间
    let cookieString = `${encodedName}=${encodedValue}; expires=${expirationDate.toUTCString()}`;

    // 如果提供了路径参数,则添加到 Cookie 字符串中
    if (path) {
        cookieString += `; path=${path}`;
    }

    // 将组合好的 Cookie 字符串赋值给 document.cookie 属性
    document.cookie = cookieString;
}

// 使用示例
setCookie('username', 'JaneDoe', 7, '/');

场景

  • 用户偏好设置:在客户端根据用户在页面上的操作(如选择主题、字体大小等)设置相应的 Cookie,以便下次访问页面时恢复用户的偏好。
  • 统计和分析:客户端可以设置一些用于统计用户行为的 Cookie,例如记录用户访问页面的次数、停留时间等。
  • 简单的状态管理:在单页面应用中,客户端可以使用 Cookie 来保存一些简单的状态信息,如用户是否已经同意了隐私政策等。

对比

  • 安全性:服务端设置的 Cookie 可以更好地控制其安全性,例如使用 HttpOnly 和 Secure 属性,防止客户端脚本访问和在非 HTTPS 连接中传输。客户端设置的 Cookie 安全性相对较低,因为 JavaScript 代码可能会受到跨站脚本攻击(XSS)的影响。

  • 作用范围:服务端可以更灵活地设置 Cookie 的作用域,包括域名、路径等。客户端设置的 Cookie 作用域通常受限于当前页面的域名和路径。

综上所述,虽然服务端设置 Cookie 更为常见和安全,但客户端设置 Cookie 在某些场景下也非常有用。

总结

Cookie 的属性决定了它的生命周期、作用范围和安全性。合理配置这些属性可以确保 Cookie 的正常使用,同时避免潜在的安全风险。以下是一些最佳实践:

  • 对于敏感数据,始终使用 HttpOnly 和 Secure 属性。
  • 根据需求设置合适的 SameSite 属性以防止 CSRF 攻击。
  • 控制 Domain 和 Path 属性的作用范围,避免不必要的 Cookie 泄露。