我正在使用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))
});
我看到要通过csrf
验证ajax
令牌,您必须在ajax请求的data
属性内指定它,而我做到了。我认为问题是由属性processData
和contentType
引起的
设置为false
。
如果我删除这些属性,则代码不会引发invalid csrf token
错误,但在浏览器中它将显示TypeError: 'append' called on an object that does not implement interface FormData.
答案 0 :(得分:0)
我发现,要上传图像并验证csrf
令牌,而不是在csrf
调用的data
属性内传递ajax
令牌,则应将其设置在内部header
调用的ajax
属性
您必须执行类似的操作
var form = $("#upload-file-form");
var fd = new FormData(form.get(0));
var token = $("#upload-file-form input[name='_csrf']").val();
$.ajax({
url: '/posts/upload' ,
headers: {"X-CSRF-TOKEN": <your token>},
data: {your datas},
dataType: 'json',
type: 'POST',
processData: false,
contentType: false
});