🛡️ CSRF 防护机制

Defense Mechanisms

📖 为什么 CSRF 能成功?

CSRF 攻击成功的关键:

  1. 浏览器会自动携带目标网站的 Cookie
  2. 服务器仅凭 Cookie 判断用户身份
  3. 服务器无法区分请求是用户主动发起还是被诱导发起

🔐 防护方案一:CSRF Token

最常用的防护方式,原理是在请求中加入攻击者无法获取的随机 Token。

工作流程

1. 用户登录时,服务器生成随机 CSRF Token
2. Token 存储在服务器 Session 中
3. 同时返回给前端(不能放在 Cookie 中!)
4. 前端每次请求时,在 Header 或 Body 中携带 Token
5. 服务器验证 Token 是否匹配

为什么攻击者拿不到 Token?

• Token 不在 Cookie 中,不会自动携带

• 同源策略阻止攻击者读取其他域的页面内容

• 攻击者无法获取 Token,请求会被拒绝

代码示例

// 服务端验证
app.post('/transfer', (req, res) => {
  const sessionToken = req.session.csrfToken
  const requestToken = req.headers['x-csrf-token']
  
  if (!requestToken || requestToken !== sessionToken) {
    return res.status(403).json({ error: 'CSRF Token 验证失败' })
  }
  
  // 执行转账...
})

// 前端请求
fetch('/transfer', {
  method: 'POST',
  headers: {
    'X-CSRF-Token': csrfToken  // 从页面获取
  },
  body: JSON.stringify({ to: 'xxx', amount: 100 })
})

🍪 防护方案二:SameSite Cookie

通过设置 Cookie 的 SameSite 属性,限制跨站请求携带 Cookie。

三种模式

说明防护效果
Strict 完全禁止跨站携带 最强,但影响用户体验
Lax 允许 GET 导航请求携带 推荐,平衡安全和体验
None 允许跨站携带(需 Secure) 无防护
// 设置 SameSite Cookie
res.cookie('session', sessionId, {
  httpOnly: true,
  secure: true,
  sameSite: 'Lax'  // 或 'Strict'
})

🔍 防护方案三:验证 Referer/Origin

检查请求的来源是否合法。

app.post('/transfer', (req, res) => {
  const origin = req.headers.origin
  const referer = req.headers.referer
  
  const allowedOrigins = ['https://bank.com']
  
  if (!allowedOrigins.includes(origin)) {
    return res.status(403).json({ error: '非法来源' })
  }
  
  // 执行转账...
})
⚠️ 注意

Referer 可能被浏览器隐私设置屏蔽,不能作为唯一防护手段

✅ 防护方案四:二次确认

对敏感操作要求用户进行二次验证:

🧪 对比测试

当前账户余额:

加载中...