【问题标题】:Ajax POST with csrfmiddlewaretoken and csrftoken cookie set still gets django 403 Forbidden带有 csrfmiddlewaretoken 和 csrftoken cookie 集的 Ajax POST 仍然得到 django 403 Forbidden
【发布时间】:2015-08-13 16:39:05
【问题描述】:

我了解到 csrfmiddlewaretoken 和 csrftoken cookie 都必须是 django POST 请求成功的正确值 (django: csrftoken COOKIE vs. csrfmiddlewaretoken HTML Form value)。对我来说就是这种情况,但我仍然得到 403:

在 chrome 控制台中:

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: 'gdasu@alumni.stanford.edu', 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 %}

我做错了什么?

【问题讨论】:

    标签: ajax django-csrf csrf-protection


    【解决方案1】:

    嗯,我找到了解决办法。它只是将数据作为 URI 而不是 json 发送。 (顺便说一下,我尝试在上面指定 dataType: 'json' 无济于事。)以下是在 chrome 控制台中:

    > email = 'gdasu@alumni.stanford.edu'
    < "gdasu@alumni.stanford.edu"
    
    > 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);
        }
    });
    

    【讨论】:

      【解决方案2】:

      您可以通过添加 csrf_exempt 来告诉视图不检查 csrf 令牌来禁止 Django 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})
      

      【讨论】:

      • 如果您使用 POST 等不安全的方法来帮助防御跨站请求伪造,则应使用 CSRF 令牌。
      猜你喜欢
      • 1970-01-01
      • 2015-08-29
      • 2016-06-07
      • 2018-06-08
      • 1970-01-01
      • 2015-11-06
      • 1970-01-01
      • 2012-11-04
      • 1970-01-01
      相关资源
      最近更新 更多