From http://sporcic.org/2012/10/csrf-with-nodejs-and-express-3:
app.use(express.csrf());
app.use(function(req, res, next){
res.locals.token = req.session._csrf;
next();
});
app.use(app.router);
To make use of above protection, does it mean I should put hidden _csrf
hidden input in ALL of my forms including admin-only pages?
One option is to add a hidden input field to all your forms as you mention. But according to the Express docs on csrf:
The default value function checks
req.body
generated by thebodyParser()
middleware,req.query
generated byquery()
, and the"X-CSRF-Token"
header field.
So depending on your client side framework, you could also use the query string or the X-CSRF-Token
alternatives.
The point remains that you need to:
- pass the
_.csrf
token from Express to your client side - return the
_.csrf
token from the client side back to Express on all your state mutating reqs (POST/PUT/DELETE) so Express can compare it against thereq.session._csrf
to complete the cycle.
For example if your client side is in Angular, the $http
module offers csrf protection by default, looking for a cookie called XSRF-TOKEN
and returning this value on all state mutating requests (POST/PUT/DELETE) through a header calledX-XSRF-TOKEN
. This is an unlucky coincidence, because the name differs from the header name where Express looks for it, which is X-CSRF-TOKEN
(notice -XSRF-
vs. -CSRF-
).
To overcome this you need to
Step 1: On the Express side augment the default value function of the CSRF middleware to look for the token value in the X-XSRF-TOKEN
header, in addition to all other default places:
app.use(express.csrf({value: function(req) {
var token = (req.body && req.body._csrf) ||
(req.query && req.query._csrf) ||
(req.headers['x-csrf-token']) ||
// This is the only addition compared to the default value function
(req.headers['x-xsrf-token']);
return token;
}
});
Step 2: On the Express side again set the token value added by the CSRF middleware under req.session._csrf
in the cookie that Angular will look for, using a custom middleware:
app.use(function(req, res, next) {
req.cookie('XSRF-TOKEN', req.session._csrf);
next();
});
Now Angular will find it and include it in the X-XSRF-TOKEN
header without any further action.
Further down in that article, the author explains that this exposes a "token" property to all of your templates that should be included on a hidden input field.
Notice the 2nd line in his jade example:
form(action='/form',method='post')
input(type='hidden', name='_csrf', value=token)
label(for='color') Color:
input(type='text',name='color',size='50')
button(type='submit') Save
来源:https://stackoverflow.com/questions/19566949/csrf-protection-in-expressjs