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 就不会报错了.