name: csrf-protection description: 使用同步令牌、双提交Cookie和SameSite属性实现CSRF保护。适用于保护Web表单、保护状态更改端点或实施深度防御认证。
CSRF保护
使用多层保护防御跨站请求伪造攻击。
保护方法
| 方法 | 工作原理 | 浏览器支持 |
|---|---|---|
| 同步令牌 | 隐藏表单字段在服务器端验证 | 所有 |
| 双提交 | Cookie + 头部必须匹配 | 所有 |
| SameSite Cookie | 浏览器阻止跨源请求 | 现代 |
基于令牌的保护(Express)
const crypto = require('crypto');
function generateToken() {
return crypto.randomBytes(32).toString('hex');
}
// 中间件
app.use((req, res, next) => {
if (!req.session.csrfToken) {
req.session.csrfToken = generateToken();
}
res.locals.csrfToken = req.session.csrfToken;
next();
});
// 验证
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
app.use(session({
cookie: {
httpOnly: true,
secure: true,
sameSite: 'strict', // 或 'lax'
maxAge: 3600000
}
}));
HTML表单集成
<form method="POST" action="/transfer">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
<button type="submit">提交</button>
</form>
最佳实践
- 应用于所有状态更改请求(POST、PUT、DELETE)
- 对敏感Cookie使用SameSite=Strict
- 验证Origin/Referer头部
- 切勿使用GET进行修改
- 实施令牌过期(通常1小时)
- 结合多层防御
额外实现
参见references/python-react.md以获取:
- Flask-WTF完整CSRF设置
- React钩子用于CSRF令牌管理
- 双提交Cookie模式
常见错误
- 假设身份验证能防止CSRF
- 跨会话重用令牌
- 将令牌存储在localStorage中
- 缺少令牌过期