0

私は Ethan Brown の本「Node と Express を使用した Web 開発」に取り組んでおり、写真のアップロードで csrf multipart/form-data アップロードを有効にするまでは順調に進んでいます。私はGithubから完全な本のコードをダウンロードしました。

エラー: 無効な 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');
};

および views/contest/vacation-photo.handlebars

<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を機能させる適切な方法は何ですか?

ありがとう、

4

2 に答える 2

1

vacation-photo 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')
})

詳細については、このリンクを確認してください。

于 2014-12-05T07:53:59.057 に答える
0

アクション URL にクエリ文字列として csrf トークンを追加します。

<form class="form-horizontal" role="form" enctype="multipart/form-data" method="POST" 
action="/contest/vacation-photo/{{year}}/{{month}}?_csrf={{_csrfToken}}">
</form>
于 2016-05-25T08:44:48.287 に答える