105 lines · 2.8 KB · JavaScript
RawDownload
 /*! * Connect - csrf * Copyright(c) 2011 Sencha Inc. * MIT Licensed */ /** * Module dependencies. */ var utils = require('../utils')  , crypto = require('crypto'); /** * CRSF protection middleware. * * By default this middleware generates a token named "_csrf" * which should be added to requests which mutate * state, within a hidden form field, query-string etc. This * token is validated against the visitor's `req.session._csrf` * property which is re-generated per request. * * The default `value` function checks `req.body` generated * by the `bodyParser()` middleware, `req.query` generated * by `query()`, and the "X-CSRF-Token" header field. * * This middleware requires session support, thus should be added * somewhere _below_ `session()` and `cookieParser()`. * * Examples: * *      var form = '\n\ *        <form action="/" method="post">\n\ *          <input type="hidden" name="_csrf" value="{token}" />\n\ *          <input type="text" name="user[name]" value="{user}" />\n\ *          <input type="password" name="user[pass]" />\n\ *          <input type="submit" value="Login" />\n\ *        </form>\n\ *      ';  *       *      connect( *          connect.cookieParser() *        , connect.session({ secret: 'keyboard cat' }) *        , connect.bodyParser() *        , connect.csrf() *       *        , function(req, res, next){ *          if ('POST' != req.method) return next(); *          req.session.user = req.body.user; *          next(); *        } *       *        , function(req, res){ *          res.setHeader('Content-Type', 'text/html'); *          var body = form *            .replace('{token}', req.session._csrf) *            .replace('{user}', req.session.user && req.session.user.name || ''); *          res.end(body); *        } *      ).listen(3000); * * Options: * *    - `value` a function accepting the request, returning the token  * * @param {Object} options * @api public */ module.exports = function csrf(options) {  var options = options || {}    , value = options.value || defaultValue;   return function(req, res, next){    // generate CSRF token    var token = req.session._csrf || (req.session._csrf = utils.uid(24));     // ignore GET (for now)    if ('GET' == req.method || 'HEAD' == req.method || 'OPTIONS' == req.method) return next();     // determine value    var val = value(req);     // check    if (val != token) return utils.forbidden(res);        next();  }}; /** * Default value function, checking the `req.body` * and `req.query` for the CSRF token. * * @param {IncomingMessage} req * @return {String} * @api private */ function defaultValue(req) {  return (req.body && req.body._csrf)    || (req.query && req.query._csrf)    || (req.headers['x-csrf-token']);}