Session绑定CSRF防护真的有效吗?我这样写对不对?

爱学习的兰兰 阅读 79

我在用 Express + EJS 做一个简单的表单提交功能,听说把 CSRF token 和 Session 绑定能防攻击,但我照着文档写了还是有点懵——后端生成的 token 存到 session 里,前端再塞进 hidden input,这样就安全了吗?

我试了下面这段代码,但不确定是不是漏了什么关键步骤,比如 token 校验逻辑或者随机性够不够……

<form method="POST" action="/submit">
  <input type="hidden" name="_csrf" value="<%= session.csrfToken %>" />
  <input type="text" name="title" />
  <button type="submit">提交</button>
</form>

后端我是用 csurf 中间件生成 token 并挂到 session 上的,但总觉得这样直接从 session 读出来放页面上,会不会被别人伪造请求时照样带上?求指点!

我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
皇甫熙炫
你的理解基本是对的,CSRF token 存在 session 里再放到表单中,这个流程本身没问题。

攻击者伪造请求时为什么无法带上正确 token?因为同源策略的限制,攻击者的网页根本读取不到你网站的 session,也拿不到那个 token。他唯一能做的就是在自己的页面构造表单提交到你的服务器,但他页面里没有正确的 token 值。

你代码里用的 csurf 其实已经 deprecated 了,不过逻辑上没毛病。它生成的 token 是加密随机的,攻击者猜不到。验证这步 csurf 中间件会自动帮你做,收到请求时会比对 session 里的 token 和表单提交的 token 是否一致,不一致就拒绝。

不过有几点注意下:

一是 csurf 依赖 express-session,你确保已经正确配置了 session 中间件且放在 csurf 之前。顺序大概是这样:

app.use(session({ secret: 'your-secret', resave: false, saveUninitialized: false }));
app.use(csrf({ cookie: false }));


二是如果你用的是 fetch 或者 axios 之类的 ajax 提交,不是传统表单,那 token 得手动放到请求头里:

fetch('/submit', {
method: 'POST',
headers: {
'X-CSRF-Token': document.querySelector('input[name="_csrf"]').value
},
body: new FormData(form)
});


传统表单提交的话你这样写就 ok 了,不用担心。
点赞
2026-03-18 18:15
迷人的颖杰
你这样做基本是对的,但缺了关键的后端验证步骤。csurf中间件默认会帮你验证,但最好自己确认下。给你个完整例子:

// 后端设置
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.use(csrfProtection);

// 路由里传token给前端
app.get('/form', (req, res) => {
res.render('form', {
csrfToken: req.csrfToken() // 会自动存session
});
});

// 提交时验证
app.post('/submit', csrfProtection, (req, res) => {
// 能执行到这里说明token验证通过了
console.log('安全的数据:', req.body);
});


前端部分你写的没问题,但要确保每个表单都有token。几个关键点:

1. token必须每次请求重新生成(csurf已经帮你做了)
2. 必须用POST/PUT/DELETE等会修改数据的请求方法
3. 别把token存在cookie里,要放session

常见漏掉的是忘记加csrfProtection中间件到POST路由,或者前端没在每个表单加token字段。你现在的代码改一下post路由就行。

伪造请求的问题是:攻击者拿不到你session里的token值,所以他们生成的假请求里token对不上。这就是为什么要把token和session绑定。
点赞 2
2026-03-05 13:01