簡體   English   中英

(Django)針對在Chrome中運行的AJAX請求的CSRF驗證,而不是Firefox

[英](Django) CSRF Verification for AJAX requests working in Chrome but not Firefox

正如標題所述,我的(Django)CSRF驗證在Chrome中運行但不在Firefox中,我想知道為什么我可以解決這個問題。

我將其包含在我的base.html文件的head標記中,我的應用程序中的所有其他文件都從該標記擴展:

base.html,head標簽的底部

    <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>

我將這段代碼放在一個名為browse.js的文件中,該文件需要向我自己的服務器發出ajax請求。

browse.js

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中運行良好。 當我在Firefox上時,它只給了我一個403 Forbidden。 這是追溯:

追溯

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>

可能有什么不對?


解決:我把@ensure_csrf_cookie放在獲取cookie的視圖上(不是ajax請求調用的函數 - 這讓我很困惑)。 現在Firefox上沒有403s了。 好極了

在您的請求標頭中,我看到:

X-CSRFToken null

所以我的猜測是在Firefox中設置了cookie。 也許它已經在之前的會話中設置在Chrome中。

Django文檔解釋了為什么這可能是

警告

如果您的視圖未呈現包含csrf_token模板標記的模板,則Django可能不會設置CSRF令牌cookie。 這在表單動態添加到頁面的情況下很常見。 為了解決這種情況,Django提供了一個視圖裝飾器來強制設置cookie:ensure_csrf_cookie()。

嘗試在views.py中導入ensure_csrf_cookie裝飾器並使用它包裝基本視圖。 例如:

from django.views.decorators.csrf import ensure_csrf_cookie

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

我不確定這是否是根本問題,但我希望這有幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM