Double Submit Cookie实战解析与前端CSRF防护经验分享
为什么我要对比这几个方案
说到CSRF防护,Double Submit Cookie算是一个比较常见的方案。不过,实现方式有很多种,比如传统的Cookie+表单隐藏字段、使用Header的Token、或者干脆用JWT。我这次打算对比一下这几种方法,看看哪个更靠谱,哪个更容易踩坑。
传统Cookie+表单隐藏字段:最经典的方式
这个方法大家都挺熟悉的,简单来说就是在客户端设置一个Cookie,然后在表单中再加一个隐藏字段,两者值相同。服务器端验证这两个值是否一致。
代码示例:
javascript
// 设置Cookie
document.cookie = "csrf_token=abc123; path=/";
// 表单中添加隐藏字段
const form = document.createElement('form');
form.method = 'POST';
form.action = '/submit';
const hiddenField = document.createElement('input');
hiddenField.type = 'hidden';
hiddenField.name = 'csrf_token';
hiddenField.value = 'abc123'; // 从Cookie中读取
form.appendChild(hiddenField);
document.body.appendChild(form);
form.submit();
这个方案的好处是简单直接,容易理解。但缺点也很明显,就是安全性不高,因为Cookie和表单数据都可能被JS读取到。而且每次请求都要手动加隐藏字段,有点麻烦。
使用Header的Token:更现代的选择
这个方法是把Token放在HTTP头里发送,而不是表单。客户端先获取到Token,然后通过Ajax请求时加上这个头。
代码示例:
javascript
// 获取Token
const token = getCookie('csrf_token');
// 发送Ajax请求
fetch('/api/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-CSRF-Token': token
},
body: JSON.stringify({ data: 'some data' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
这个方案我觉得更灵活,特别是对于API请求,不用每次都修改表单。而且Token在Header里,比放在表单里安全一点。但是,需要确保所有请求都加上这个Header,否则还是有风险。
JWT:一石二鸟的方法
JWT(JSON Web Token)其实也可以用来做CSRF防护,虽然它主要是用来做认证的。我们可以把Token放在JWT里,然后在每次请求时都带上JWT。
代码示例:
javascript
// 获取JWT
const jwt = getCookie('jwt');
// 发送Ajax请求
fetch('/api/submit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': Bearer ${jwt}
},
body: JSON.stringify({ data: 'some data' })
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
这个方案的优点是一次解决了认证和CSRF的问题,而且Token在JWT里加密了,安全性更高。不过,JWT本身也有不少坑,比如过期时间、刷新机制等,需要好好设计。
谁更灵活?谁更省事?
从实际使用角度来看,我比较喜欢用Header的Token方法。首先,它比传统的Cookie+表单隐藏字段更灵活,特别是在处理API请求时。其次,它比JWT简单,不需要额外处理JWT的过期和刷新问题。当然,JWT确实是个好东西,但如果你只是为了CSRF防护,那有点杀鸡用牛刀的感觉。
具体选哪个还是要看场景。如果是传统的表单提交,那就用Cookie+表单隐藏字段吧,简单粗暴。如果是API为主的项目,我一般选Header的Token。如果需要同时解决认证和CSRF问题,那可以考虑JWT。
性能对比:差距比我想象的大
性能方面,其实这几个方案差别不大。但是,传统的Cookie+表单隐藏字段可能会稍微慢一点,因为它需要在每个表单里手动加隐藏字段。而Header的Token和JWT则更轻量级,特别是JWT,只需要在请求头里加一个Token,非常高效。
不过,这里要注意我踩过好几次坑的地方:JWT的过期时间一定要设置合理,否则会频繁刷新Token,影响性能。另外,如果Token太大,也会影响传输效率。
我的选型逻辑
总结一下,我个人的经验是这样的:
- 如果是传统的表单提交,就用Cookie+表单隐藏字段,简单直接。
- 如果是API为主的项目,推荐用Header的Token,灵活且高效。
- 如果需要同时解决认证和CSRF问题,可以考虑JWT,但要做好Token管理。
以上是我的对比总结,有不同看法欢迎评论区交流。希望这些经验对你有帮助!

暂无评论