Django CSRF 使用 ajax 失败

发布于 2024-12-19 00:42:23 字数 3798 浏览 0 评论 0原文

我在使用 Django CSRF 和 Ajax 时遇到问题。我收到 403 Forbidden。我已经完成了通常使用非 ajax 请求执行的所有 CSRF 操作,但我仍然遇到这个问题。我认为这与 https 处的 javascript 片段有关: //docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

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

我目前没有使用这个片段,主要是因为我一个字也不明白,而且我不知道如何将它合并到我的 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',
          });
}

有谁知道我应该如何将此片段添加到我的代码中?

也尝试过:

$.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的事情

谢谢

I have a problem with using Django CSRF with Ajax. I get a 403 Forbidden. I have done all the CSRF things that I normally do with a non-ajax request, but I still have this problem. I'm thinking this has something to do with the javascript snippet at https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax.

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

I'm not currently using this snippet, mostly because I don't understand a word of it and I don't know how to incorporate it into my jquery ajax call:

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',
          });
}

Does anyone know how I should go about adding this snippet to my code?

Also tried:

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

but this also does not seem to work, although I'm not sure whether I should be doing something for the bit about #csrfmiddlewaretoken in my form

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情话已封尘 2024-12-26 00:42:23

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

All you need to do is paste the code block in such a way that the code in it runs. If you have a global JS file, you should be able to just add that JavaScript to the end of said file, and it will fix the problem.

夜清冷一曲。 2024-12-26 00:42:23

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

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

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

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

一样类似,

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请求中,您应该像一个小技巧 您可能会错过的是,您的着陆页(非- ajax)将需要 @csrf_protect 装饰器来设置 cookie,如果不这样做,cookie 将不存在并且该方法将失败。如果您不想使用 @csrf_protect 装饰器,您可以随时参考文档并专门设置 cookie。无论哪种方式都会起作用。

希望这有帮助。

well, couple steps required as stated in https://docs.djangoproject.com/en/dev/ref/contrib/csrf/

To summarize the tedious django doc, you will need to:
1. install jquery.cookie plugins
2. make sure crsf_token is passing around

for example, in your template, the form must contain the following hidden field

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

In your ajax request, you should so similar things like

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)
 });

one small tricks that you might be missing is, your landing page(non-ajax) will need @csrf_protect decorator to set up cookie, if you don't do that, the cookie won't exists and the method will fail. If you don't want to do @csrf_protect decorator, you can always refer back to the doc and specifically setup the cookie. Either way will work.

Hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文