当使用enctype =“multipart / form-data”时,我得到CSRF错误

每当我添加enctype =“multipart / form-data”到我的html表单,我得到“ForbiddenError:无效的csrf标记”如果我删除enctype,它的工作原理我发送的csrf代码是这样的:input(type =“hidden “name =”_ csrf“value = csrf_token)

我的快递文件:

var express = require('express'); var session = require('express-session'); var compression = require('compression'); var cookieParser = require('cookie-parser'); var cookieSession = require('cookie-session'); var bodyParser = require('body-parser'); var methodOverride = require('method-override'); var csrf = require('csurf'); var env = process.env.NODE_ENV || 'development'; module.exports = function (app, passport) { // Compression middleware (should be placed before express.static) app.use(compression({ threshold: 512 })); // Static files middleware app.use(express.static(config.root + '/public')); // set views path and default layout app.set('views', config.root + '/app/views'); app.set('view engine', 'jade'); // bodyParser should be above methodOverride app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.json()); app.use(methodOverride(function (req, res) { if (req.body && typeof req.body === 'object' && '_method' in req.body) { // look in urlencoded POST bodies and delete it var method = req.body._method; delete req.body._method; return method; } })); // cookieParser should be above session app.use(cookieParser()); app.use(cookieSession({ secret: 'secret' })); app.use(session({ secret: pkg.name, proxy: true, resave: true, saveUninitialized: true, store: new mongoStore({ url: config.db, collection : 'sessions' }) })); // use passport session app.use(passport.initialize()); app.use(passport.session()); // connect flash for flash messages - should be declared after sessions // adds CSRF support if (process.env.NODE_ENV !== 'test') { app.use(csrf()); app.use(function(req, res, next){ res.locals.csrf_token = req.csrfToken(); next(); }); } }; 

我的表单:

 form(action="/adminfruta/criarproduto" enctype="multipart/form-data" method="post") input(type="hidden" name="_csrf" value= csrf_token) .tipo Tipo do Produto input(type="radio", value="cesta", name="type", id="cesta", checked="checked") label.radio(for="cesta") Cesta input(type="radio", value="avulso", name="type", id="avulso") label.radio(for="avulso") Avulso label(for="name") Nome do Produto: input(type="text" name="name" id="name") label(for="code") Código da Cesta no sistema input(type="text" name="code" id="code") label(for="inventory") Estoque: input(type="number" name="inventory") label(for="description") Descrição: //- textarea#description(name="description") select(multiple="multiple" name="description" id="descricao") for item in itens option(value= item.id)= item.name label(for="quantities") Quantidade de cada item, de acordo com a ordem da lista (não da ordem que você selecionou) separado por virgulas input(type="text" name="quantities" id="quantities" placeholder="Exemplo: 3,1,1,4,2,6") .fotos .half //- .pic //- img(src="/img/produto.png", alt="") .choose Escolha foto 1 (tamanho 250x250 px): input(type="file" name="foto1") .half //- .pic //- img(src="/img/produto.png", alt="") .choose Escolha foto 2 (tamanho 250x250 px): input(type="file" name="foto2") .fotos .half label(for="price") Preço(em centavos): input(type="number" name="price" placeholder="R$86,00 ficaria 8600") .half label(for="discount") Desconto (opcional): input(type="number" name="discount") .tipo Categorias: ul.categories for category in categories li input(type="radio" value= category.id id= category.name name="category") label(for= category.name) #{category.name} .tipo Produtos Relacionados: .relations select(id="related_products" name="related_products" multiple="multiple") for product in products option(value= product.id)= product.name .tipo Adicionais: .relations select(id="addons" name="addons" multiple="multiple") for item in itens option(value= item.id) #{item.name} button.button.save(type="submit") Criar Novo 

我的路线文件

 var mongoose = require('mongoose'); var admin = require('admin'); var aws = require('aws-sdk'); var multer= require('multer'); var multerS3 = require('multer-s3'); var s3 = new aws.S3({/*params: {Bucket: 'frutacor'}*/}); // var upload = multer({ dest: 'public/img/users/' }); var upload = multer({ storage: multerS3({ s3: s3, bucket: 'frutacor', acl: 'public-read', key: function (req, file, cb) { cb(null, Date.now().toString()); } }) }); module.exports = function (app, passport) { app.post('/adminfruta/criarproduto', admin.verifyAdmin, upload.fields([ {name: 'foto1', maxCount: 1}, {name: 'foto2', maxCount: 1}]), admin.createProduct); } 

最后是admin.js文件

 exports.createProduct = function(req, res){ var product = new Product(makeProduct(req.body, req.files)); console.log(product); product.save(); return res.render('admin/index'); }; var makeProduct = function(product, photos){ console.log(photos); product.quantities = product.quantities.split(','); product.description = _.map(product.description, function(val, index){ return { item: val, quantity: product.quantities[index] }; }); console.log(product.description); delete product.quantities; product.photos = []; product.photos.push(photos.foto1[0].location); product.photos.push(photos.foto2[0].location); return product; }; 

另外,对于依赖关系:

 "dependencies": { "async": "1.3.0", "aws-sdk": "^2.4.2", "body-parser": "1.13.2", "chai": "^3.4.1", "compression": "1.5.1", "connect-flash": "0.1.1", "connect-mongo": "0.8.1", "cookie-parser": "1.3.5", "cookie-session": "1.2.0", "csurf": "1.9.0", "dotenv": "^2.0.0", "easyimage": "^2.1.0", "express": "4.13.1", "express-session": "1.11.3", "forever": "0.14.2", "jade": "^1.11.0", "method-override": "2.3.3", "mongoose": "4.0.6", "mongoose-user": "latest", "morgan": "1.6.1", "multer": "^1.1.0", "multer-s3": "^2.3.2", "passport": "0.2.2", "passport-local": "1.0.0", "request": "^2.69.0", "sha1": "^1.1.1", "underscore": "^1.8.3", "view-helpers": "0.1.5", "winston": "1.0.1", "xml2json": "^0.9.1" } 

我以为是因为这个原因,但后来我改变了multer版本,并停止使用它作为一个全球性的中间件,我仍然得到这个错误。

注意:如果在我的URL后面更改动作以包含“?_csrf =#{csrfToken}”,但是我想要一个更清晰的解决scheme(如果有)。

使这样的forms

 <form method="post" action="/?_csrf=<%=csrfToken%>" 

并删除这个

 input(type="hidden" name="_csrf" value= csrf_token)