Ajax POST с набором файлов cookie csrfmiddlewaretoken и csrftoken по-прежнему получает django 403 Forbidden

Я читал, что и csrfmiddlewaretoken, и файл cookie csrftoken должны иметь правильное значение для успешного выполнения запроса POST django (django: csrftoken COOKIE и значение HTML-формы csrfmiddlewaretoken). Это касается меня, но я все еще получаю 403:

В хромированной консоли:

document.cookie

возвращается

"csrftoken=Wt9eeJop5Vb3OmeNTvogegckm1pVM5MD"

но

$.get('https://learningdollars.fwd.wf/csrftoken/', function(data){
    console.log(data)
    token = $.parseHTML(data)[0].value
    console.log(token)
    $.ajax({
        type: "POST",
        url: 'https://learningdollars.fwd.wf/confirmemail/',
        data: {email: '[email protected]', csrfmiddlewaretoken: token},
        contentType: "application/json"
    })
    .done(function(response) {
        console.log('done!')
    })
    .fail(function(error) {
        console.log('fail!')
    })
})

возвращается

> Object {readyState: 1, getResponseHeader: function, getAllResponseHeaders: function, setRequestHeader: function, overrideMimeType: function…}
> <input type='hidden' name='csrfmiddlewaretoken' value='Wt9eeJop5Vb3OmeNTvogegckm1pVM5MD' />
> Wt9eeJop5Vb3OmeNTvogegckm1pVM5MD
> POST https://learningdollars.fwd.wf/confirmemail/ 403 (Forbidden)
> fail! 

У меня есть

'django.middleware.csrf.CsrfViewMiddleware',

активирован в моем промежуточном программном обеспечении django.

Мой корневой urls.py содержит:

url(r'^csrftoken/$', views.get_csrf_token),
url(r'^confirmemail/$', views.confirm_email, name='confirm_email'),

И мои взгляды таковы:

def get_csrf_token(request):
    c = {}
    c.update(csrf(request))
    print c
    return render_to_response('csrf.html', c)

def confirm_email(request):
    print 'here'
    return JsonResponse({'response': 0})

И, кстати, содержимое csrf.html — это просто csrftoken (внутри входного тега):

{% csrf_token %}

Что я делаю не так?


person Gobi Dasu    schedule 06.10.2014    source источник


Ответы (2)


Ну, я нашел решение. Он просто отправлял данные как URI, а не как json. (Кстати, я пытался указать dataType: 'json' выше, но безрезультатно.) В консоли chrome:

> email = '[email protected]'
< "[email protected]"

> csrftoken = 'L2MxD1XQIF1Xto5NkzUgGUYiHPyyz3K5'
< "L2MxD1XQIF1Xto5NkzUgGUYiHPyyz3K5"

> $.ajax({
    type: "POST",
    url: 'https://learningdollars.fwd.wf/confirmemail/',
    data: "email="+ encodeURI(email) + "&csrfmiddlewaretoken=" + encodeURI(csrftoken),
    success: function(data) { console.log(data); }
})

< Object {response: 1}

Все еще не уверен, что я делал неправильно на стороне json, но я пробовал следующее:

$.ajax({
    type: "POST",
    url: "https://learningdollars.fwd.wf/confirmemail/",
    data: JSON.stringify({ email: email, csrfmiddlewaretoken: csrftoken }),
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function(data){
        alert(data);
    },
    failure: function(errMsg) {
        alert(errMsg);
    }
});
person Gobi Dasu    schedule 07.10.2014

Вы можете запретить Django CSRF, добавив csrf_exempt, чтобы представление не проверяло токен csrf.

from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def get_csrf_token(request):
    c = {}
    c.update(csrf(request))
    print c
    return render_to_response('csrf.html', c)

@csrf_exempt
def confirm_email(request):
    print 'here'
    return JsonResponse({'response': 0})
person ybdesire    schedule 13.08.2015
comment
Токен CSRF следует использовать, если вы используете небезопасные методы, такие как POST, для защиты от подделки межсайтовых запросов. - person Bono; 10.12.2015