阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 防御 CSRF 的常见方法(如 Token 验证)

防御 CSRF 的常见方法(如 Token 验证)

作者:陈川 阅读数:39256人阅读 分类: 前端安全

防御 CSRF 的常见方法(如 Token 验证)

CSRF(Cross-Site Request Forgery)是一种常见的网络攻击方式,攻击者通过伪造用户身份执行非预期的操作。防御 CSRF 的方法多种多样,其中 Token 验证是最常用的手段之一。除了 Token 验证,还可以通过 SameSite Cookie、双重 Cookie 验证等方式增强安全性。

Token 验证的原理

Token 验证的核心思想是在请求中携带一个随机生成的令牌(Token),服务器通过验证该令牌的合法性来判断请求是否可信。Token 通常存储在用户的会话(Session)或 Cookie 中,并在表单提交或 AJAX 请求时发送给服务器。

Token 的生成和验证流程如下:

  1. 用户访问页面时,服务器生成一个随机 Token 并存储在 Session 中。
  2. 服务器将 Token 嵌入到页面表单或返回给前端。
  3. 用户提交表单或发送请求时,Token 随请求一起发送到服务器。
  4. 服务器验证 Token 是否与 Session 中存储的一致。
// 示例:生成 CSRF Token(Node.js + Express)
const express = require('express');
const csrf = require('csurf');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(csrf({ cookie: true }));

app.get('/form', (req, res) => {
  res.send(`
    <form action="/process" method="POST">
      <input type="hidden" name="_csrf" value="${req.csrfToken()}">
      <button type="submit">Submit</button>
    </form>
  `);
});

app.post('/process', (req, res) => {
  // 中间件会自动验证 CSRF Token
  res.send('Form processed successfully');
});

Token 的存储与传递方式

Token 可以通过多种方式传递给前端,常见的方式包括:

  1. 表单隐藏字段:将 Token 作为隐藏字段嵌入表单中。

    <form action="/submit" method="POST">
      <input type="hidden" name="_csrf" value="随机生成的Token">
      <!-- 其他表单字段 -->
    </form>
    
  2. HTTP 请求头:在 AJAX 请求中通过请求头传递 Token。

    fetch('/api/data', {
      method: 'POST',
      headers: {
        'X-CSRF-Token': '随机生成的Token'
      }
    });
    
  3. Cookie + 请求头:将 Token 存储在 Cookie 中,前端读取后通过请求头发送。

    // 从 Cookie 中读取 Token
    const token = document.cookie.replace(/(?:(?:^|.*;\s*)XSRF-TOKEN\s*\=\s*([^;]*).*$|^.*$/, '$1');
    
    fetch('/api/data', {
      method: 'POST',
      headers: {
        'X-XSRF-Token': token
      }
    });
    

SameSite Cookie 属性

SameSite 是 Cookie 的一个属性,用于限制 Cookie 的跨站发送行为。它可以有效防止 CSRF 攻击,尤其是在现代浏览器中广泛支持的情况下。

SameSite 有三个可选值:

  • Strict:Cookie 仅在同站请求中发送。
  • Lax:Cookie 在跨站请求中部分允许发送(如导航跳转)。
  • None:Cookie 在所有请求中发送(需配合 Secure 属性)。
// 设置 SameSite Cookie(Node.js)
res.cookie('sessionID', '12345', {
  httpOnly: true,
  secure: true,
  sameSite: 'Strict'
});

双重 Cookie 验证

双重 Cookie 验证是另一种防御 CSRF 的方法。其原理是将 Token 同时存储在 Cookie 和请求参数中,服务器验证两者是否一致。

实现步骤:

  1. 用户访问页面时,服务器在 Cookie 中设置一个随机 Token。
  2. 前端从 Cookie 中读取 Token,并在请求时将其作为参数或请求头发送。
  3. 服务器比对 Cookie 中的 Token 和请求中的 Token。
// 示例:双重 Cookie 验证
app.get('/api/data', (req, res) => {
  const token = req.cookies['CSRF-TOKEN'];
  const requestToken = req.headers['x-csrf-token'];
  
  if (token && requestToken && token === requestToken) {
    res.send('Valid request');
  } else {
    res.status(403).send('Invalid CSRF Token');
  }
});

其他防御措施

除了上述方法,还可以结合以下措施增强安全性:

  1. 验证 Referer 和 Origin 头:检查请求的来源是否合法。

    app.use((req, res, next) => {
      const referer = req.get('Referer');
      if (referer && !referer.startsWith('https://yourdomain.com')) {
        return res.status(403).send('Invalid request source');
      }
      next();
    });
    
  2. 限制敏感操作的 HTTP 方法:确保敏感操作(如修改数据)仅允许 POST、PUT、DELETE 等方法。

    app.post('/change-password', (req, res) => {
      // 处理密码修改逻辑
    });
    
  3. 短期有效的 Token:为 Token 设置较短的过期时间,减少被利用的风险。

    app.use(csrf({ cookie: { maxAge: 3600 } })); // Token 1 小时后过期
    

实际应用中的注意事项

  1. 避免 Token 泄露:Token 不应出现在 URL 或日志中,防止被截获。
  2. 前后端分离架构的适配:在 SPA(单页应用)中,可以通过接口获取 Token 并存储在内存中。
    // 前端获取 CSRF Token
    fetch('/csrf-token', { credentials: 'include' })
      .then(res => res.json())
      .then(data => {
        window.csrfToken = data.token;
      });
    
  3. 兼容旧版浏览器:如果使用 SameSite Cookie,需考虑旧版浏览器的兼容性问题。

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌