Django CSRF 使用 ajax 失败

Posted

技术标签:

【中文标题】Django CSRF 使用 ajax 失败【英文标题】:Django CSRF failing with ajax 【发布时间】:2012-01-10 00:53:42 【问题描述】:

我在将 Django CSRF 与 Ajax 结合使用时遇到问题。我得到一个 403 禁止。我已经完成了我通常使用非 ajax 请求所做的所有 CSRF 事情,但我仍然遇到这个问题。我认为这与https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax 的javascript sn-p 有关。

$(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'));
   
);

我目前没有使用这个 sn-p,主要是因为我一个字都不懂,也不知道如何将它合并到我的 jquery ajax 调用中:

function submit_search()

   $.ajax(
             data:     query: document.search_form.query.value,
             datatype: 'json',
             success:  function(data, textStatus, XMLHttpRequest)
                       
                          if (data)
                          
                             if (check_authentication(data))
                             
                                $("#results").html("");
                                var results = data[0];
                                var length = data[1];
                                for (var index = 0; index < results.length; ++index)
                                
                                   var result = results[index];
                                   $("#results").append("<p><a href='/entities/" + result["id"] + "'>" + result["name"] +
                                                        "</a><br />" + result["description"] + "</p>");
                                
                             
                             else
                             
                                offer_login();
                             
                          
                       ,
             type:     'POST',
             url:      '/ajax/search',
          );

有谁知道我应该如何将这个 sn-p 添加到我的代码中?

也试过了:

$.ajaxSetup(
    beforeSend: function(xhr, settings) 
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) 
            // Only send the token to relative URLs i.e. locally.
            xhr.setRequestHeader("X-CSRFToken",
                                 $("#csrfmiddlewaretoken").val());
        
    
);

但这似乎也不起作用,虽然我不确定我是否应该在我的表单中为#csrfmiddlewaretoken 做一些事情

谢谢

【问题讨论】:

【参考方案1】:

您需要做的就是粘贴代码块,使其中的代码能够运行。如果你有一个全局 JS 文件,你应该可以只将那个 JavaScript 添加到所述文件的末尾,它会解决问题。

【讨论】:

谢谢,没想到这么简单。我现在已经出现内部服务器错误。 @Superdooperhero “即使是在 a** 中踢一脚也是向前迈进了一步”:)【参考方案2】:

嗯,需要几个步骤,如https://docs.djangoproject.com/en/dev/ref/contrib/csrf/中所述

总结乏味的 django 文档,您需要: 1.安装jquery.cookie插件 2. 确保 crsf_token 正在传递

例如,在您的模板中,表单必须包含以下隐藏字段

<input type="hidden" name="csrfmiddlewaretoken" value="csrf_token"/>

在你的 ajax 请求中,你应该有类似的东西

csrf_token = $.cookie('csrftoken');
$.ajax(
   url: '/url/',
           type: 'POST',
           beforeSend: function(xhr, settings) 
               xhr.setRequestHeader("X-CSRFToken", csrf_token);
            ,
           data: $('.form').serialize(), //assume you are submit a form
 ).done(function(response)
         console.log(response)
 );

您可能缺少的一个小技巧是,您的登录页面(非 ajax)将需要 @csrf_protect 装饰器来设置 cookie,如果您不这样做,cookie 将不存在并且该方法将失败.如果您不想使用 @csrf_protect 装饰器,您可以随时参考文档并专门设置 cookie。无论哪种方式都可以。

希望这会有所帮助。

【讨论】:

你救了我的一天

以上是关于Django CSRF 使用 ajax 失败的主要内容,如果未能解决你的问题,请参考以下文章

Django-ajax:CSRF 验证失败。请求中止

错误:“CSRF 验证失败。请求中止。”在 Django 中使用 jquery ajax 时

仅在 Opera 上的 ajax 发布请求上的 Django CSRF 失败

Django Rest Framework,ajax POST 工作,但 PATCH 抛出 CSRF 失败:CSRF 令牌丢失或不正确

CSRF错误Django ajax .post没有表格

带有 django 的 JQuery AJAX 获取 csrf 错误 403