Double Submit Cookie实战解析与前端CSRF防护经验分享

轩辕秀花 安全 阅读 2,797
赞 56 收藏
二维码
手机扫码查看
反馈

为什么我要对比这几个方案

说到CSRF防护,Double Submit Cookie算是一个比较常见的方案。不过,实现方式有很多种,比如传统的Cookie+表单隐藏字段、使用Header的Token、或者干脆用JWT。我这次打算对比一下这几种方法,看看哪个更靠谱,哪个更容易踩坑。

Double Submit Cookie实战解析与前端CSRF防护经验分享

传统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管理。

以上是我的对比总结,有不同看法欢迎评论区交流。希望这些经验对你有帮助!

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论