(Django的)CSRF验证了AJAX请求在Chrome而不是Firefox的工作 [英] (Django) CSRF Verification for AJAX requests working in Chrome but not Firefox

查看:971
本文介绍了(Django的)CSRF验证了AJAX请求在Chrome而不是Firefox的工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

正如标题状态,我(Django的)CSRF验证工作在Chrome浏览器,但没有Firefox和我想知道为什么这样我就可以解决这个问题。

As the title states, my (Django) CSRF verification is working in Chrome but not Firefox and I'd like to know why so I can fix this.

我有,这包括在的的标签我的 base.html 文件从我的应用程序的所有其他文件扩展:

I have this included in the head tag of my base.html file from which all other files in my application extend:

    <script>
    $(document).ready(function() {

        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;
        }
        var csrftoken = getCookie('csrftoken');
        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
    });
    </script>

和我有这个code在一个名为文件,该文件需要做出Ajax请求到我自己的服务器 browse.js

And I have this code in a file called browse.js which needs to make ajax requests to my own server.

Template = {
  setup : function(){
    Template.events.csrf();
    // etc. etc.
  },
  events: {
    csrf : function(){
      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;
      }
      var csrftoken = getCookie('csrftoken');
      function csrfSafeMethod(method) {
        // these HTTP methods do not require CSRF protection
        return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
      }
      $.ajaxSetup({
        beforeSend: function(xhr, settings) {
          if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
          }
        }
      });
    },
//etc. etc.
}
//The actual ajax request
Data = {
  api : {
    ajax_get_listings : function(cb){
      var g, i, o, _ref;
      _ref = [
        $('#ci').val(), 
        $('#co').val(), 
        $('#guests').val()], 
        i = _ref[0], 
        o = _ref[1], 
        g = _ref[2];
      if (g) {
        console.log('getting listings');
        return $.ajax({
          url:'/api/get_listing_items/', 
          type: 'POST',
          datatype:'json',
          data: {
            available_start_date: i,
            available_end_date: o,
            max_guests: g
          }, 
          success: function(d) {
            if (d.listings !== null){
              Data.listings._results = [];
              console.log(d);
              var l = $.parseJSON(
                $("<textarea/>").html(d.listings).text());
              console.log(l);
              data = l;
              console.log(data);
              return cb(data);
            }else{ 
              $('#ct').text('No listings found for your search criteria. Please keep searching!');
            }
          },
        });
      }
    },
  },
//etc. etc
}

此外,这工作正常的Chrome浏览器。它只是给了我403当我在Firefox中禁止。这里是回溯:

Again, this works fine in Chrome. It only gives me a 403 Forbidden when I am on Firefox. Here is the traceback:

view source
Content-Type    
text/html
Date    
Mon, 19 Oct 2015 22:06:07 GMT
Server  
WSGIServer/0.1 Python/2.7.3
Vary    
Cookie
X-Frame-Options 
SAMEORIGIN
view source
Accept  
*/*
Accept-Encoding 
gzip, deflate
Accept-Language 
en-US,en;q=0.5
Cache-Control   
no-cache
Connection  
keep-alive
Content-Length  
54
Content-Type    
application/x-www-form-urlencoded; charset=UTF-8
Cookie  
_ga=GA1.1.1619904474.1445292335; _gat=1; TawkConnectionTime=0;      __tawkuuid=e||127.0.0.1||mnW1PFpM4y26O8w
+2HatshrE3nWV4w3xD7SAtEMYGtV647bMojOwsqzNlPdxYCdB||2;     Tawk_560d98fcc096ea637ec4b8c0=vs15.tawk.to:443
||0
DNT 
1
Host    
127.0.0.1:8008
Pragma  
no-cache
Referer 
http://127.0.0.1:8008/properties/
User-Agent  
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0
X-CSRFToken 
null
X-Requested-With    
XMLHttpRequest  

响应

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="robots" content="NONE,NOARCHIVE">
  <title>403 Forbidden</title>
  <style type="text/css">
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font:small sans-serif; background:#eee; }
    body>div { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; margin-bottom:.4em; }
    h1 span { font-size:60%; color:#666; font-weight:normal; }
    #info { background:#f6f6f6; }
    #info ul { margin: 0.5em 4em; }
    #info p, #summary p { padding-top:10px; }
    #summary { background: #ffc; }
    #explanation { background:#eee; border-bottom: 0px none; }
  </style>
</head>
<body>
<div id="summary">
  <h1>Forbidden <span>(403)</span></h1>
  <p>CSRF verification failed. Request aborted.</p>


  <p>You are seeing this message because this site requires a CSRF cookie     when submitting forms.       This
 cookie is required for security reasons, to ensure that your browser is not     being hijacked by third
 parties.</p>
      <p>If you have configured your browser to disable cookies, please re-enable them, at least for this
 site, or for &#39;same-origin&#39; requests.</p>

</div>

<div id="info">
  <h2>Help</h2>
    <p>Reason given for failure:</p>
    <pre>
      CSRF cookie not set.
    </pre>
    <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
  <a
  href='http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-   csrf'>Django's
  CSRF mechanism</a> has not been used correctly.  For POST forms, you need to
  ensure:</p>

      <ul>
      <li>Your browser is accepting cookies.</li>

    <li>The view function uses <a
     href='http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-  context-requestcontext'
><code>RequestContext</code></a>
    for the template, instead of <code>Context</code>.</li>

    <li>In the template, there is a <code>{% csrf_token
%}</code> template tag inside each POST form that
targets an internal URL.</li>

   <li>If you are not using <code>CsrfViewMiddleware</code>, then you must   use <code>csrf_protect</code> on any views that use the <code>csrf_token</code>
template tag, as well as those that accept the POST data.</li>
</ul><p>You're seeing the help section of this page because you have <code>DEBUG =
  True</code> in your Django settings file. Change that to   <code>False</code>,
 and only the initial error message will be displayed.  </p>

   <p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
</div>

</body>
</html>

什么地方出错了?

What could be wrong?

解决的:我把@ensure_csrf_cookie上越来越Cookie中的观点(而不是AJAX请求调用函数 - 这混淆了我)。在Firefox没有更多的403s现。耶

SOLVED: I put @ensure_csrf_cookie on the view that was getting the cookie (NOT the function the ajax request was calling -- this had confused me). No more 403s on Firefox now. Yay

推荐答案

在您的请求标头,我看到:

In your request headers, I see:

X-CSRFToken空

X-CSRFToken null

所以我的猜测是,该cookie是在Firefox中被设置。也许它已经在Chrome从previous会话设置。

So my guess is that the cookie is being set in Firefox. Perhaps it was already set in Chrome from a previous session.

Django文档解释了原因之一可能被的:

警告

如果你的观点并没有呈现包含csrf_token模板   模板标签,Django的,还没有设置CSRF令牌的cookie。这是   常见于其中的形式被动态添加到页面箱子。至   针对这种情况,Django提供了一个视图修饰它的力量   Cookie的设置。)ensure_csrf_cookie(

If your view is not rendering a template containing the csrf_token template tag, Django might not set the CSRF token cookie. This is common in cases where forms are dynamically added to the page. To address this case, Django provides a view decorator which forces setting of the cookie: ensure_csrf_cookie().

尝试导入 ensure_csrf_cookie 装饰在views.py和包装的基本视图它。例如:

Try importing the ensure_csrf_cookie decorator in your views.py and wrapping your base view with it. Ex:

from django.views.decorators.csrf import ensure_csrf_cookie

@ensure_csrf_cookie
def base_view(request):
    # do stuff
    return render('base.html', {...})

我不知道这是根本的问题,但我希望这会有所帮助!

I'm not sure if this is the root issue, but I hope this helps!

这篇关于(Django的)CSRF验证了AJAX请求在Chrome而不是Firefox的工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆