【发布时间】:2019-11-18 07:08:42
【问题描述】:
我正在与mongodb、nodejs 和express 合作。
我有一个发送post 请求以使用multer-gridfs 上传文件的表单。
在表单中,我只有input 用于上传文件,hidden input 用于csrf。请求通过ajax 发送。问题是我发送 ajax 请求时对csrf token 的验证
上传图片的表格
<form enctype='multipart/form-data' id="upload-file-form" enctype="multipart/form-data" >
<input type="file" name="file" id="file">
<input type="hidden" name="_csrf" value="<%= csrfToken %>">
</form>
AJAX
function upload_image(){
console.log('upload image')
var fd = new FormData($("#upload-file-form").get(0));
console.log(fd);
var token = $('input[name="_csrf"]').val();
$.ajax({
url: '/posts/upload' ,
data: {fd: fd, _csrf: token },
dataType: 'json',
type: 'POST',
processData: false,
contentType: false,
success: function (response) {
console.log(response);
},
error: function (xhr, status, error) {
console.log('Error: ' + error.message);
}
})
}
错误
ForbiddenError: invalid csrf token
at csrf (/home/pero/motoWebApp/node_modules/csurf/index.js:112:19)
at Layer.handle [as handle_request] (/home/pero/motoWebApp/node_modules/express/lib/router/layer.js:95:5)
at trim_prefix (/home/pero/motoWebApp/node_modules/express/lib/router/index.js:317:13)
at /home/pero/motoWebApp/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/home/pero/motoWebApp/node_modules/express/lib/router/index.js:335:12)
at next (/home/pero/motoWebApp/node_modules/express/lib/router/index.js:275:10)
at Immediate.<anonymous> (/home/pero/motoWebApp/node_modules/express-session/index.js:495:7)
at runCallback (timers.js:706:11)
at tryOnImmediate (timers.js:676:5)
at processImmediate (timers.js:658:5)
监听 AJAX 请求的路由
const GridFsStorage = require('multer-gridfs-storage'),
multer = require('multer');
const mongoURI = "mongodb://localhost:27017/app";
// Create storage engine
const storage = new GridFsStorage({
url: mongoURI,
file: (req, file) => {
return new Promise((resolve, reject) => {
crypto.randomBytes(16, (err, buf) => {
if (err) {
return reject(err);
}
const filename = buf.toString('hex') + path.extname(file.originalname);
const fileInfo = {
filename: filename,
bucketName: 'uploaded_images' //collection name
};
resolve(fileInfo);
});
});
}
});
const upload = multer({
storage: storage,
});
router.post('/posts/upload', upload.single('file'), function(req, res){
res.send(JSON.stringify(req.file.filename))
});
我看到,为了通过ajax 验证csrf toke,您必须在ajax 请求的data 属性中指定它,我这样做了。我认为问题是由processData 和contentType 属性引起的
设置为false。
如果我删除这些属性,代码不会引发invalid csrf token 错误,但在浏览器中会打印TypeError: 'append' called on an object that does not implement interface FormData.
【问题讨论】:
-
您是否使用了合适的会话中间件/cookie-parser?
-
是的,我找到了解决办法
标签: node.js ajax express multer