csrf-protection

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

CSRF Protection

CSRF防护

Defend against Cross-Site Request Forgery attacks using multiple protection layers.
通过多层防护机制抵御跨站请求伪造(Cross-Site Request Forgery)攻击。

Protection Methods

防护方法

MethodHow It WorksBrowser Support
Synchronizer TokenHidden form field validated server-sideAll
Double SubmitCookie + header must matchAll
SameSite CookieBrowser blocks cross-origin requestsModern
方法工作原理浏览器支持
同步令牌(Synchronizer Token)通过服务器端验证隐藏表单字段所有浏览器
双重提交(Double Submit)Cookie与请求头必须匹配所有浏览器
SameSite Cookie浏览器阻止跨源请求现代浏览器

Token-Based Protection (Express)

基于令牌的防护(Express)

javascript
const crypto = require('crypto');

function generateToken() {
  return crypto.randomBytes(32).toString('hex');
}

// Middleware
app.use((req, res, next) => {
  if (!req.session.csrfToken) {
    req.session.csrfToken = generateToken();
  }
  res.locals.csrfToken = req.session.csrfToken;
  next();
});

// Validation
app.post('*', (req, res, next) => {
  const token = req.body._csrf || req.headers['x-csrf-token'];
  if (!token || !crypto.timingSafeEqual(
    Buffer.from(token),
    Buffer.from(req.session.csrfToken)
  )) {
    return res.status(403).json({ error: 'Invalid CSRF token' });
  }
  next();
});
javascript
const crypto = require('crypto');

function generateToken() {
  return crypto.randomBytes(32).toString('hex');
}

// Middleware
app.use((req, res, next) => {
  if (!req.session.csrfToken) {
    req.session.csrfToken = generateToken();
  }
  res.locals.csrfToken = req.session.csrfToken;
  next();
});

// Validation
app.post('*', (req, res, next) => {
  const token = req.body._csrf || req.headers['x-csrf-token'];
  if (!token || !crypto.timingSafeEqual(
    Buffer.from(token),
    Buffer.from(req.session.csrfToken)
  )) {
    return res.status(403).json({ error: 'Invalid CSRF token' });
  }
  next();
});

SameSite Cookies

SameSite Cookie配置

javascript
app.use(session({
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict', // or 'lax'
    maxAge: 3600000
  }
}));
javascript
app.use(session({
  cookie: {
    httpOnly: true,
    secure: true,
    sameSite: 'strict', // or 'lax'
    maxAge: 3600000
  }
}));

HTML Form Integration

HTML表单集成

html
<form method="POST" action="/transfer">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <button type="submit">Submit</button>
</form>
html
<form method="POST" action="/transfer">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <button type="submit">Submit</button>
</form>

Best Practices

最佳实践

  • Apply to all state-changing requests (POST, PUT, DELETE)
  • Use SameSite=Strict for sensitive cookies
  • Validate Origin/Referer headers
  • Never use GET for modifications
  • Implement token expiration (1 hour typical)
  • Combine multiple defense layers
  • 应用于所有状态变更请求(POST、PUT、DELETE)
  • 敏感Cookie使用SameSite=Strict
  • 验证Origin/Referer请求头
  • 绝不要使用GET请求进行数据修改
  • 实现令牌过期机制(通常为1小时)
  • 组合使用多种防御层

Additional Implementations

其他实现方式

See references/python-react.md for:
  • Flask-WTF complete CSRF setup
  • React hooks for CSRF token management
  • Double submit cookie pattern
查看references/python-react.md获取以下内容:
  • Flask-WTF完整CSRF配置
  • React hooks管理CSRF令牌
  • 双重提交Cookie模式

Common Mistakes

常见错误

  • Assuming authentication prevents CSRF
  • Reusing tokens across sessions
  • Storing tokens in localStorage
  • Missing token expiration
  • 认为身份认证可以防止CSRF
  • 跨会话重复使用令牌
  • 将令牌存储在localStorage中
  • 未设置令牌过期时间