元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
注入攻击与防御
SQL注入原理与利用
SQL注入防御策略
NoSQL注入技术分析
命令注入漏洞实战
ORM框架注入问题
注入攻击自动化检测
▶
认证与会话安全
会话固定与会话劫持
密码存储与加密策略
多因素认证机制
OAuth2.0安全实践
JWT安全攻防
认证逻辑漏洞挖掘
▶
XSS攻击与防御
XSS攻击原理与分类
存储型XSS实战案例
DOM型XSS高级利用
XSS过滤器绕过技术
CSP内容安全策略
前端框架XSS防护
▶
CSRF与点击劫持
CSRF攻击原理演示
CSRF Token防御实践
点击劫持技术剖析
SameSite Cookie策略
框架内置防护机制
跨域资源安全策略
▶
文件安全攻防
文件上传漏洞利用
安全文件类型验证
路径遍历漏洞实战
文件包含漏洞防御
Office文档攻击解析
云存储安全配置
▶
其他Web攻击技术
SSRF漏洞利用与防御
XXE漏洞攻防实战
反序列化漏洞原理
业务逻辑漏洞挖掘
HTTP请求走私攻击
Web缓存投毒攻击
发布时间:
2025-03-23 13:13
↑
☰
# CSRF Token防御实践 ## CSRF Token原理 CSRF Token是防御CSRF攻击的最有效方法之一。它通过在每个表单中添加一个随机生成的令牌,并在服务器端验证该令牌的有效性来确保请求来自合法的用户。本文将详细介绍CSRF Token的实现原理和最佳实践。 ## 实现方案 ### 1. 基本实现 ```javascript // CSRF Token生成器 class CSRFTokenGenerator { constructor() { this.tokenLength = 32; } // 生成随机Token generateToken() { return crypto .randomBytes(this.tokenLength) .toString('hex'); } // 验证Token verifyToken(token, storedToken) { if (!token || !storedToken) { return false; } // 使用时间安全的比较函数 return crypto.timingSafeEqual( Buffer.from(token), Buffer.from(storedToken) ); } } // Express中间件实现 app.use((req, res, next) => { // 生成Token const token = new CSRFTokenGenerator() .generateToken(); // 存储Token req.session.csrfToken = token; // 在模板中使用Token res.locals.csrfToken = token; next(); }); // 验证中间件 function validateCSRFToken(req, res, next) { const token = req.body._csrf || req.headers['x-csrf-token']; if (!new CSRFTokenGenerator() .verifyToken(token, req.session.csrfToken)) { return res.status(403).json({ error: 'Invalid CSRF token' }); } next(); } ``` ### 2. 双重提交Cookie模式 ```javascript // 双重提交Cookie实现 class DoubleSubmitCookie { constructor() { this.cookieName = 'csrf-token'; this.headerName = 'X-CSRF-Token'; } // 设置Token Cookie setTokenCookie(res) { const token = crypto .randomBytes(32) .toString('hex'); res.cookie(this.cookieName, token, { httpOnly: false, secure: true, sameSite: 'strict' }); return token; } // 验证Token verifyToken(req) { const cookieToken = req.cookies[this.cookieName]; const headerToken = req.headers[this.headerName]; return cookieToken && headerToken && cookieToken === headerToken; } } // 使用示例 app.use((req, res, next) => { const csrf = new DoubleSubmitCookie(); csrf.setTokenCookie(res); next(); }); app.post('/api/*', (req, res, next) => { const csrf = new DoubleSubmitCookie(); if (!csrf.verifyToken(req)) { return res.status(403).json({ error: 'Invalid CSRF token' }); } next(); }); ``` ### 3. 加密Token ```javascript // 加密Token实现 class EncryptedToken { constructor(secret) { this.algorithm = 'aes-256-gcm'; this.secret = crypto .createHash('sha256') .update(secret) .digest(); } // 生成加密Token generateToken(userId) { // 生成随机IV const iv = crypto.randomBytes(12); // 创建加密器 const cipher = crypto.createCipheriv( this.algorithm, this.secret, iv ); // 加密数据 const timestamp = Date.now(); const data = JSON.stringify({ userId, timestamp }); let encrypted = cipher.update( data, 'utf8', 'hex' ); encrypted += cipher.final('hex'); // 获取认证标签 const authTag = cipher.getAuthTag(); // 组合Token return Buffer.concat([ iv, Buffer.from(encrypted, 'hex'), authTag ]).toString('base64'); } // 验证Token verifyToken(token, userId) { try { // 解码Token const buffer = Buffer.from(token, 'base64'); // 提取各个部分 const iv = buffer.slice(0, 12); const authTag = buffer.slice(-16); const encrypted = buffer .slice(12, -16) .toString('hex'); // 创建解密器 const decipher = crypto.createDecipheriv( this.algorithm, this.secret, iv ); decipher.setAuthTag(authTag); // 解密数据 let decrypted = decipher.update( encrypted, 'hex', 'utf8' ); decrypted += decipher.final('utf8'); const data = JSON.parse(decrypted); // 验证用户ID和时间戳 return data.userId === userId && Date.now() - data.timestamp < 3600000; // 1小时有效期 } catch { return false; } } } ``` ## 前端实现 ### 1. 表单提交 ```javascript // CSRF Token管理器 class CSRFManager { constructor() { this.token = document .querySelector('meta[name="csrf-token"]') ?.getAttribute('content'); } // 添加Token到表单 addTokenToForm(form) { if (!this.token) return; const input = document.createElement('input'); input.type = 'hidden'; input.name = '_csrf'; input.value = this.token; form.appendChild(input); } // 添加Token到AJAX请求 addTokenToRequest(xhr) { if (!this.token) return; xhr.setRequestHeader( 'X-CSRF-Token', this.token ); } } // 自动处理所有表单 document.addEventListener('DOMContentLoaded', () => { const csrf = new CSRFManager(); // 处理现有表单 document.querySelectorAll('form').forEach(form => { csrf.addTokenToForm(form); }); // 监听动态添加的表单 const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(node => { if (node.nodeName === 'FORM') { csrf.addTokenToForm(node); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); }); ``` ### 2. AJAX请求 ```javascript // Fetch API包装器 class SecureFetch { constructor() { this.csrf = new CSRFManager(); } async fetch(url, options = {}) { // 添加CSRF Token if (!options.headers) { options.headers = {}; } if (this.csrf.token) { options.headers['X-CSRF-Token'] = this.csrf.token; } // 添加其他安全头部 options.credentials = 'same-origin'; return fetch(url, options); } async post(url, data) { return this.fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }); } } // Axios拦截器 axios.interceptors.request.use(config => { const csrf = new CSRFManager(); if (csrf.token) { config.headers['X-CSRF-Token'] = csrf.token; } return config; }); ``` ## 最佳实践 ### 1. 安全配置 ```javascript // CSRF安全配置 const csrfConfig = { // Token配置 token: { length: 32, httpOnly: true, secure: true, sameSite: 'strict' }, // 请求验证 validation: { enabled: true, ignoreMethods: ['GET', 'HEAD', 'OPTIONS'], ignoreRoutes: ['/public/', '/api/webhook/'], allowedOrigins: ['https://example.com'] }, // Cookie设置 cookie: { name: 'csrf-token', path: '/', domain: '.example.com', maxAge: 3600 }, // 头部设置 headers: { request: 'X-CSRF-Token', response: 'X-CSRF-Token' } }; ``` ### 2. 错误处理 ```javascript // CSRF错误处理 class CSRFErrorHandler { constructor() { this.errors = new Map(); } // 处理验证错误 handleValidationError(req, error) { const errorId = crypto.randomBytes(8) .toString('hex'); this.errors.set(errorId, { timestamp: Date.now(), url: req.url, method: req.method, headers: req.headers, error: error.message }); // 记录错误日志 console.error( `CSRF Validation Error [${errorId}]:`, error.message ); return errorId; } // 获取错误详情 getError(errorId) { return this.errors.get(errorId); } // 清理过期错误 cleanup() { const now = Date.now(); for (let [id, error] of this.errors) { if (now - error.timestamp > 3600000) { this.errors.delete(id); } } } } ``` ## 总结 CSRF Token防护需要从多个层面实施: 1. 服务器端 - 生成安全的Token - 验证Token有效性 - 正确配置Cookie 2. 客户端 - 自动添加Token - 处理验证失败 - 实施安全策略 3. 配置管理 - 设置安全选项 - 处理错误情况 - 监控异常行为