0

I have a set up a Django server and want to access it by a Phonegap application using ajax. This works well so far. Now I try to upload a file to the server, but I am getting status code 403 FORBIDDEN.

I think this is because I use a form to upload the file and csrf does not work right.

The csrf token is pulled on login:

def login(request):
...
response = {
    ...
    'csrf' : get_new_csrf_key()
}
return HttpResponse(json.dumps(response), content_type='json')

and stored in public R.user.csrf

Server upload view:

from django.middleware.csrf import _get_new_csrf_key as get_new_csrf_key
from django.middleware.csrf import CsrfViewMiddleware

...

def uploadfile(request):
    ...
    if request.is_ajax():
        form = UploadForm(request.POST, request.FILES)
        u_file = request.FILES['upload']
        extension = u_file.name.split(".")[-1]

        upload = File(
            data = u_file,
            owner = user,
            fileid = newfid,
            name = 'newfile',
            description = u_file.name,
            createdat = timezone.now(),
            type = extension
        )
        upload.save()
        response = {
            'head' : 'Success',
            'message' : 'Filed uploaded!',
            'time' : '3000',
            'fileid' : newfid
        }

    return HttpResponse(json.dumps(response), content_type='json')

Application ajax call:

var uploadFile = function(){
    console.log('uploading file...');
    updateLoader(1);
    var selectFile = $('#selectfile');
    var file = new FormData($('#uploadForm')[0]);
    var request = $.ajax({
        type : "POST",
        url : R.urls.uploadfile,
        data : {
            'file' : file,
            csrfmiddlewaretoken : R.user.csrf
        },
        processData : false,
        contentType : false,
        error : function(response) {
            console.log('upload failed!');
            updateLoader(-1);
            showMessage("Failed", "Something went wrong...", 3000);
            selectFile.replaceWith(selectFile = selectFile.clone(true));
        },
        success : function(data) {
            console.log('upload successful!');
            updateLoader(-1);
            var filename = $('#filename').val();
            var parent = $('#parentfolder').val();
            sendReRequest(data.fileid, filename, parent);
            selectFile.replaceWith(selectFile = selectFile.clone(true));
        }
    });
};

HTML:

<input class="inputfield" type="text" id="parentfolder" name="parentfolder"><br/>
<input class="inputfield" type="text" id="filename" name="filename"  placeholder="Give your file a name"><br/>
<form id="uploadForm" method="post" enctype="multipart/form-data">
    <input class="inputfield" id="selectfile" type="file" name="upload"><br/>
    <input id="uploadfilebutton" type="submit" value="Upload" />
</form>

I also tried:

var csrfSafeMethod = function(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
};

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", R.user.csrf);
        }
    }
});

What do I miss? Thanks!

work.b
  • 23
  • 1
  • 5
  • If you want, you can disable Django's CSRF validation by applying csrf_exempt() decoration on your view. See: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#django.views.decorators.csrf.csrf_exempt – frbry Oct 01 '14 at 22:06
  • Thanks for the hint! I tried it. Now the FORBIDDEN status code is gone. But `request.is_ajax()` is FALSE now... – work.b Oct 02 '14 at 07:59
  • Ok fixed this, too. Adding `crossDomain: false` to the ajax request as mentioned [here](http://stackoverflow.com/questions/7755899/django-says-is-ajax-is-false-on-a-jquery-ajax-request) fixed the problem. – work.b Oct 02 '14 at 08:11

0 Answers0