2014-12-04 82 views
0

我正在通过Ethan Brown的书“用节点和快车进行Web开发”一直工作,直到我启用了csrf在照片上的multipart/form-data上传上传。我下载了Github上,https://github.com/EthanRBrown/web-development-with-node-and-express完整书籍代码和做同样的事情,一直工作到CSRF已启用,它的错误与:Express4和强大的文件上传工作,直到我启用csrf

错误:无效的CSRF令牌

这里是我认为相关的代码位,/meadowlark.js起始于线100

app.use(require('cookie-parser')(credentials.cookieSecret)); 
app.use(require('express-session')({ store: sessionStore, 
      secret: credentials.cookieSecret, 
      name: credentials.cookieName, 
      saveUninitialized: true, 
      resave: true })); 
app.use(express.static(__dirname + '/public')); 
app.use(require('body-parser')()); 

// cross-site request forgery protection 
app.use(require('csurf')()); 
app.use(function(req, res, next){ 
    res.locals._csrfToken = req.csrfToken(); 
    next(); 
}); 

// database configuration 
var mongoose = require('mongoose'); 
var options = { 
    server: { 
     socketOptions: { keepAlive: 1 } 
    } 
}; 

然后在/handlers/contest.js

var path = require('path'), 
    fs = require('fs'), 
    formidable = require('formidable'); 

// make sure data directory exists 
var dataDir = path.normalize(path.join(__dirname, '..', 'data')); 
var vacationPhotoDir = path.join(dataDir, 'vacation-photo'); 
fs.existsSync(dataDir) || fs.mkdirSync(dataDir); 
fs.existsSync(vacationPhotoDir) || fs.mkdirSync(vacationPhotoDir); 

exports.vacationPhoto = function(req, res){ 
    var now = new Date(); 
    res.render('contest/vacation-photo', { year: now.getFullYear(), month: now.getMonth() }); 
}; 

function saveContestEntry(contestName, email, year, month, photoPath){ 
    // TODO...this will come later 
} 

exports.vacationPhotoProcessPost = function(req, res){ 
    var form = new formidable.IncomingForm(); 
    form.parse(req, function(err, fields, files){ 
     if(err) return res.redirect(303, '/error'); 
     if(err) { 
      res.session.flash = { 
       type: 'danger', 
       intro: 'Oops!', 
       message: 'There was an error processing your submission. ' + 
        'Pelase try again.', 
      }; 
      return res.redirect(303, '/contest/vacation-photo'); 
     } 
     var photo = files.photo; 
     var dir = vacationPhotoDir + '/' + Date.now(); 
     var path = dir + '/' + photo.name; 
     fs.mkdirSync(dir); 
     fs.renameSync(photo.path, dir + '/' + photo.name); 
     saveContestEntry('vacation-photo', fields.email, 
      req.params.year, req.params.month, path); 
     req.session.flash = { 
      type: 'success', 
      intro: 'Good luck!', 
      message: 'You have been entered into the contest.', 
     }; 
     return res.redirect(303, '/contest/vacation-photo/entries'); 
    }); 
}; 

exports.vacationPhotoEntries = function(req, res){ 
    res.render('contest/vacation-photo/entries'); 
}; 

和意见/竞赛/度假photo.handleba rs

<form class="form-horizontal" role="form" 
     enctype="multipart/form-data" method="POST" 
     action="/contest/vacation-photo/{{year}}/{{month}}"> 
    <input type="hidden" name="_csrf" value="{{_csrfToken}}"> 
    <div class="form-group"> 
     <label for="fieldName" class="col-sm-2 control-label">Name</label> 
     <div class="col-sm-4"> 
      <input type="text" class="form-control" 
      id="fieldName" name="name"> 
     </div> 
    </div> 
    <div class="form-group"> 
     <label for="fieldEmail" class="col-sm-2 control-label">Email</label> 
     <div class="col-sm-4"> 
      <input type="email" class="form-control" required 
       id="fieldName" name="email"> 
     </div> 
    </div> 
    <div class="form-group"> 
     <label for="fieldPhoto" class="col-sm-2 control-label">Vacation photo</label> 
     <div class="col-sm-4"> 
      <input type="file" class="form-control" required accept="image/*" 
       id="fieldPhoto" data-url="/upload" name="photo"> 
     </div> 
    </div> 
    <div class="form-group"> 
     <div class="col-sm-offset-2 col-sm-4"> 
      <button type="submit" class="btn btn-primary">Submit</button> 
     </div> 
    </div> 
</form> 

什么是使csrf工作的正确方法?

感谢,

回答

1

度假,照片GET请求,就发送CSRF令牌像下面。

exports.vacationPhotoEntries = function(req, res){ 
    res.render('contest/vacation-photo/entries', { _csrfToken: req.csrfToken()}); 
}; 

您还可以赶上CSRF令牌错误在默认的错误处理程序如下图所示。

// error handler 
app.use(function (err, req, res, next) { 
    if (err.code !== 'EBADCSRFTOKEN') return next(err) 

// handle CSRF token errors here 
res.status(403) 
res.send('session has expired or form tampered with') 
}) 

欲了解更多信息,请查看this link

0

追加csrf令牌作为查询字符串的行动Url .. 它的工作原理!

<form class="form-horizontal" role="form" enctype="multipart/form-data" method="POST" 
action="/contest/vacation-photo/{{year}}/{{month}}?_csrf={{_csrfToken}}"> 
</form> 
+0

感谢查法人,我忘记了所有关于这个问题,因为我的应用程序是内部的,我刚搬到这条路线的CSRF中间件之前,直到我能回来,并修复它。你的解决方案有效 现在看它似乎很简单,我想当时我的头不在正确的地方。 我会^你的回应,但我没有足够的声望点。 – HyperSprite 2016-05-27 23:52:22