Error: invalid csrf token

当你的Express 升级到4.0+版本后,有没有遇到过下面这个问题.

{ 
  [Error: invalid csrf token]
  expose: true,
  code: 'EBADCSRFTOKEN',
  statusCode: 403,
  status: 403 
}

上面的错误是在node.js 运行环境的命令行报出来的.页面直接返回了500服务器错误.

我执行了什么操作?

这是我的一个新站 三思悦 ,此站有个功能是邀请注册,不对外公开注册的.

所以管理后台有个页面用来显示 邀请码,同时有个按钮,用来生成验证码,一次生成唯一不重复的50个.

所以这个页面对应2个相同的url ,只不过get方式用来呈现为被使用的邀请码,post 方式用来生成50个验证码并刷新本页.

其中 post 涉及到一个 form 提交.

上面报错的 csrf 是什么? 引用百度百科的一段说法

"CSRF(Cross-site request forgery跨站请求伪造,也被称为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。"

风险:

"风险在于那些通过基于受信任的输入form和对特定行为无需授权的已认证的用户来执行某些行为的web应用。已经通过被保存在用户浏览器中的cookie进行认证的用户将在完全无知的情况下发送HTTP请求到那个信任他的站点,进而进行用户不愿做的行为。"

那么Express 中为什么要有这个 csrf ? 原因就是为了避免 上面提到的风险,防止被 CSRF攻击.

在Express 中如何开启:

var csurf = require('csurf'); //使用前要 npm install csurf
app.use(function (req, res, next) {
    csurf()(req, res, next);
    next();
});

下面用一个客户端公共变量来储存此值

app.use(function (req, res, next) {
  res.locals.csrf = req.csrfToken ? req.csrfToken() : '';
  next();
});

这样我在页面中 直接用 <%- csrf %> 就可以得到此值. 

而上面的报错,正是因为post 的form 里面没有提交这个 csrfToken 值,导致上面的代码赋值时报错.

客户端可以用隐藏字段保存此值

<input type='hidden' name='_csrf' value='<%= csrf %>'/>

这样提交 Express 就不会报错了.

回到顶部