Django AJAX POST 在 IE、EDGE 等中登录 CSRF 错误

Django AJAX POST login CSRF error in IE, EDGE, etc

我正在使用 Django 1.10。

我想通过 Jquery AJAX 登录,但 CSRF 已设置。

为了通过CSRF检查,我有以下代码(在独立的js文件中)。

   /*  CSRF-config Start */
$.ajaxSetup({ 
     beforeSend: function(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;
         }
         if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
             // Only send the token to relative URLs i.e. locally.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         }
     } 
});
$(document).ajaxSend(function( event, xhr, settings ) {
    if (settings.type == 'POST' || settings.type == 'PUT' || settings.type == 'DELETE') {
        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;
        }
        if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
            // Only send the token to relative URLs i.e. locally.
            xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
        }
    }
});
    /*  CSRF-config End */    

Chrome 在这里完美运行,登录没有问题。

但是,当我切换到IE、Edge等时出现如下错误:

"""

已禁止(未设置 CSRF cookie。):/login/

[25/Aug/2016 08:58:42] "POST /login/ HTTP/1.1" 403 2857

"""

我的代码似乎根本不起作用。 :(

这里!我想出了一个解决方案。

以下代码应写入模板html页面

不要将它留给独立的 JS 文件。

删除其他相关CSRF AJAXSetup代码以防冲突

<!-- Bla bla bla your login form, input, etc. -->
<script>
  $.ajaxSetup({
      data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
  });
</script>

来自 Django 文档:

If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. Read more...

您可以通过以下两种解决方案之一使用现有的静态 JS:

  1. 确保在模板中包含 {% csrf_token %}。通常它以表格形式出现,但如果您不使用表格,只需将其放在正文中的某个位置即可。
  2. @ensure_csrf_cookie 装饰器添加到您的视图函数中。

我过去只在 IE 上遇到过这个问题