由于自Django 1.2.5以来AJAX请求的CSRF策略发生了变化,所以Uploadify的所有实现似乎都被打破了。有一些尝试和一些相当模糊的答案,但还没有解决方案。现在唯一的解决方法似乎是使用@csrf_exempt装饰器,如本文所述:Fixing django csrf error when using uploadify
尽管Paul McMillan指出了这个问题的原因,但他没有提出解决方案(除了学习Actionscript和重写Uploadify)。对于任何使用Django和jQuery的人来说,在这个主题上更具体一点会很有趣,因为不是每个人都有时间学习动作脚本。我特别好奇是否可以使用Uploadify的脚本数据选项解决方案,我无法开始工作。$('#fileInput').uploadify({
'uploader' : '{{ uploadify_path }}uploadify.swf',
'script' : '{% url uploadify_upload %}',
//this is the interesting line
'scriptData': {"CSRF-Token" : $('input[name="csrfmiddlewaretoken"]').val()}
},
'cancelImg' : '{{ uploadify_path }}cancel.png',
'auto' : false,
'folder' : '{{ upload_path }}',
'multi' : true,
'onAllComplete' : allComplete
});
我认为这可行,script-data选项中指定的数据确实出现在request.POST dict中。我用pdb检查并查找请求:
@csrf_exempt
def upload(request, *args, **kwargs):
if request.method == 'POST':
if request.FILES:
upload_received.send(sender='uploadify', data=request.FILES['Filedata'])
import pdb; pdb.set_trace();
return HttpResponse(request)
这就是结果:
<WSGIRequest
GET:<QueryDict: {}>,
POST:<QueryDict: {u'CSRF-Token': [u'de885c962f9a2e50fec140e161ca993e'], u'folder': [u'/static/uploads/'], u'Upload': [u'Submit Query'], u'Filename': [u'P4010040.JPG']}>,
COOKIES:{},
META:{'App
and so on, the rest as expected
这几乎与上述帖子的回答中提出的解决方案相同,但该解决方案将破坏CSRF保护。我可以以某种方式使用scriptData来传递CSRF验证,而不会破坏保护吗?我需要哪些信息才能通过验证,我该如何使用它?
修改
我提到的帖子使用了这个解决方案,打破了csrf-protection:
使用Javascript:
biscuit = document.cookie;
csrt = $('input[name="csrfmiddlewaretoken"]').val();
$('#file_upload').uploadify({
// pass the cookie and the csrftoken
scriptData : {biscuit: biscuit, csrfmiddlewaretoken: csrf},
.... // other codes
});
中间件:
#insert after: 'django.middleware.common.CommonMiddleware'
def process_request(self, request):
if (request.method == 'POST'):
if request.POST.has_key('biscuit'):
biscuit = request.POST['biscuit']
tmp = map(lambda x: tuple(x.split("=")), biscuit.split(" "))
# set a cookie
request.COOKIES.update(tmp)
如果直接检查csrfmiddlewaretoken和session_id的正确值会怎么样?主要问题是Djangos CSRF保护依赖于CSRF cookie,而uploadify不会传递cookie。但它可以通过scriptData传递csrfmiddlewaretoken和session_id的值。它不会保留CSRF保护,告诉Django不要查找csrf-cookie,而是查找request.POST中的相关值吗?
我本来想说的是:不要盲目地设置“饼干”,但是在检查了重要值后(csrfmiddlewaretoken,sessionid,还有什么?)。我认为这可行,尽管我不确定我是否完全理解csrf保护的机制......
答案 0 :(得分:0)
我遇到了和你一样的问题。
从Django 1.2.5开始,Django会检查所有请求的CSRF。原因是因为Google人员找到了如何使用自定义标头向任何URL伪造请求的方法。所以现在验证Django CSRF的唯一方法是使用CSRF_token cookie,或者发送一个具有CSRF令牌值的X-CSRFToken头。有关此问题的发行说明可以在here找到。
根据我的理解到目前为止,无法在Uploadify中修复它,因为Uploadify使用SWFObject实际发送数据,这是Flash和Flash不允许添加自定义标头。
然而,This上传程序纯粹通过使用XHR对象发送数据或者回退到iFrame用于非支持的浏览器(我没有更改以检查解决方案,但是当它回退到iFrame但是它可以工作完美地使用XHR对象时)。另外它是基于jQuery的。 Here是如何在Django中实现此上传器的演示实现,但它仍然是CSRF免除。
为此演示启用CSRF验证的方法是从Django文档(here)添加JS snipped for jQuery。它剪切了它在jQuery中覆盖默认的AJAX行为并在每个AJAX请求上添加自定义头(X-CSRFToken)和CSRF令牌的值。现在由于上传器是基于jQuery的,因此它所做的所有AJAX请求都将是CSRF有效的。
这是剪辑(再次来自Django文档):
$(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
希望这有帮助。
答案 1 :(得分:0)
延迟回复但除了上述内容之外,如果使用csrftoken
cookie,请使用装饰器来确保设置。
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def home(request):
....