表单提交时 form submit 直接就可以提交了,但是了防止跨站攻击,都可以加入CSRF来防御。
node下的配置
var csrf = require('csurf');
app.use(csrf());
app.use(function(req, res, next){
let _csrf = req.csrfToken();
res.locals.csrf = _csrf;
res.cookie('XSRF-TOKEN', _csrf);
return next();
});
页面
<form id="localimage" action="/login" method="POST">
<input id="csrf" type="hidden" name="_csrf" value="<%= csrf %>">
<input id="test" name="test" class="test" type="text">
</form>
这么写当然没问题,但是当上传文件就不行了。
需要设置表单的enctype属性, 默认enctype 是对所有字符进行编码了的,同时csrf值就不能放到input 进行提交,从csrf源码来看我们传输csrf值可以放在以下几个地方
<form id="localimage" action="/login?_csrf=<%= csrf %>" method="POST" enctype="multipart/form-data">
<input id="imguploadinput" name="upfile" class="imguploadinput" type="file" accept="image/jpeg,image/gif,image/png,image/bmp">
</form>
ajax异步提交,也是如此,但文件时也 new FormData 提交的,csrf 放在FormData 里也不行。最好的就是放在请求头里
xhr.setRequestHeader('csrf-token', _csrf);
在ueditor里就很容易做了,ueditor里 是有ajax 方法提交的,但是没有支持file的,使用ue的方法默认就对表单信息进行了编码
可以将此方法修改一下就行了
addEvent(imguploadinput, 'change', function() {
// var localImage = document.getElementById('localimage');
// localImage.submit();
var ajax = UE.ajax;
// 图片
var file = document.getElementById('imguploadinput').files[0];
var form = new FormData();
form.append('file', file);
ajax.request('/ueditor/ue?action=uploadimage', {
method: 'POST',
timeout: 10000,
async: true,
data: form,
_csrf: csrf.value,
onsuccess: function ( xhr ) {
console.log( xhr.responseText );
},
//请求失败或者超时后的回调。
onerror: function ( xhr ) {
alert( 'Ajax请求失败' );
}
});
});
ueditor 可以修改如下
成功提交后 返回如下
否则 没有设置header 时
如果设置了
xhr.setRequestHeader("Content-Type","multipart/form-data"); 也是不行的
写死后就出现找不到Boundary(用户分割不同的字段)的错误的错误
注意 使用jquery 的ajax 提交时 ,contentType 需要设置为false
contentType:false