#14182 closed (fixed)
CsrfViewMiddleware makes modification of the upload handlers impossible
Reported by: | dc | Owned by: | Luke Plant |
---|---|---|---|
Component: | File uploads/storage | Version: | 1.2 |
Severity: | Keywords: | csrf upload_handlers | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
CsrfViewMiddleware accesses request.POST and makes modification of the upload handlers on a per-request basis impossible.
Currently it's impossible to simultaneously use per-request upload handlers and csrf protection. At least this must be documented.
See also: http://docs.djangoproject.com/en/1.2/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly
Steps to reproduce
Put attached upload_test.py in PYTHONPATH.
Start new default django project:
$ django-admin.py startproject project
Modify project/urls.py:
urlpatterns = patterns('', (r'^upload/$', 'upload_test.upload_file'), )
Open browser at /upload/ and submit form.
Actual Results
AttributeError at /upload/
You cannot alter upload handlers after the upload has been processed.
Expected Results
Normal form handling in upload_file() view.
Attachments (1)
Change History (5)
by , 14 years ago
Attachment: | upload_test.py added |
---|
comment:1 by , 14 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
Hmmm, tricky, I can't think of a nice way to get this to work automatically. If you use csrf_exempt
can you work around this? Something like this:
from django.views.decorators.csrf import csrf_exempt, csrf_protect ## Added @csrf_exempt ## Added def upload_file(request): request.upload_handlers.insert(0, DummyUploadHandler()) return upload_file_real(request) ## Added @csrf_protect ## Added def upload_file_real(request) ## Added if request.method == 'POST': form = UploadFileForm(request.POST, request.FILES) if form.is_valid(): template = Template(''' <!DOCTYPE html> <title></title> <h1>Done</h1> ''') context = RequestContext(request) return HttpResponse(template.render(context)) else: form = UploadFileForm() template = Template(''' <!DOCTYPE html> <title></title> <form action="." enctype="multipart/form-data" method="post"> {% csrf_token %} {{ form }} <input type="submit"> </form> ''') context = RequestContext(request, {'form': form}) return HttpResponse(template.render(context))
Does that work? If it does, would you mind coming up with a patch for the documentation?
comment:2 by , 14 years ago
Replying to lukeplant:
Using @csrf_exempt
and @csrf_protect
work, insofar that it's possible to add a custom upload handler that way.
However, something worth noting is that if you do this, your upload handlers will be receiving file data _before_ the CSRF checks are done. It might be worth mentioning this also in Django documentation - upload handlers receive data which hasn't been checked for CSRF yet.
comment:3 by , 14 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
Test file