2015-08-03 19 views
5

Bir arka uç olarak Django REST Framework kullanan bir proje üzerinde çalışıyorum (api.somecompany.com diyelim ama bir React.js önyükü var (www.somecompany.com) AJAX istekte Django tarafından sunulmaz.Bir CSRF belirteci bir API olarak Django almak/vermek nasıl

Ben, bu nedenle, şablon sahip Django'nın geleneksel yöntem kullanamaz

Django DİNLENME Framework'ün api-auth\login\ uRL'ye bir istekte bulunabilirsiniz bu <form action="." method="post">{% csrf_token %}

gibi CSRF kodu şu , bu başlığa dönecek: Set-Cookie:csrftoken=tjQfRZXWW4GtnWfe5fhTYor7uWnAYqhz; expires=Mon, 01-Aug-2016 16:32:10 GMT; Max-Age=31449600; Path=/ - ama AJAX istekleri ile geri göndermek için bu çerezi alamıyorum h X-CSRFToken (benim anlayışım ayrı alt etki alanıdır) ve otomatik olarak eklenmiyor gibi görünüyor.

$.ajax(loginUrl, { method: "OPTIONS", async: false }) 
    .done(function(data, textStatus, jqXHR) { 
     console.log(jqXHR) 
     [email protected] = $.cookie("csrftoken") 
     console.log($.cookie("csrftoken")) 
     console.log(app.csrftoken) 
    }) 
    .fail(function(jqXHR, textStatus, errorThrown) { 
     console.log(jqXHR) 
    }); 

Bu tam temiz değil ama kanıtlanmış değil: Eminim bir belirteç var olmak için bu çağrı sayfa yüklendikten olarak

// using jQuery 
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 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)) { 
      xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken')); 
     } 
    } 
}); 

:

İşte benim alakalı kod henüz kendime kavram.

Ön uç ve arka uç farklı bağlantı noktalarında/etki alanlarında olduğunda, CSRF'ye karşı kimlik doğrulamanın/korunmanın 'doğru' yolu nedir?

cevap

1

Aslında, bu işi, izin verilen istek kaynaklarının beyaz listesini kullanarak CSRF korumasıyla yapabilirsiniz.

Bunu yapmak için Cross-Origin Resource Sharing (CORS) kullanmak zorundasınız. Bunu başarmak için, çapraz paylaşım bilgilerinizi oluşturan bir orta sınıf sınıfı oluşturmanızı öneririz. Çapraz kaynaklı HTTP istek başlıklarında yapının bir kısmını nasıl kullanacağınızı özetleyen bir great gist var. İsterseniz, CSRF jetonunu bu yolla, istek için kök referans değerlerini değiştirerek ekleyebilirsiniz.

django-cors-headers uygulaması sizin için bunu yapar. İlgilendiğiniz takdirde, CSRF jetonlarını their middleware file numaralı telefondan nasıl pazarladıklarını görebilirsiniz.

Bu konuda daha fazla bilgi için Django REST CORS Docs'a bakın (django-cors-header'ları kullanmanızı öneririz). hala sorun yaşıyorsanız

, deneyin:

  1. True için AJAX isteği crossDomain parametresini ayarlayarak. Bazen, jQuery bu belirtilmemişse isteği işleyemez.
  2. Hala istekte bir belirteç üstbilgisi almıyorsanız, görünümünüzün çevresinde ensure_csrf_cookie() dekoratörünü eklemeyi deneyin. Bazen, sayfada {% csrf_token %} şablon etiketi olmadığında (bir form oluşturmuyorsanız), Django isteğindeki belirteci hiçbir şekilde içermez.
+0

Sanırım bu kapsamda zaten var - isteğim CORS nedenleriyle başarısız oluyor. Anlayabildiğim kadarıyla, ilk isteğimin ("OPTIONS") "csrftoken" çerezini ayarlamaması, bir başlık olarak eklemek için okuyamıyorum veya bir sonraki ile otomatik olarak gönderilmesini istemiyorum. istek. Doğrudan bir istekte bulunmak (AJAX kullanmamak), çerezi uygun şekilde ayarlar. Kurabın ayarlanmasını engelleyen bir şey var mı? – jimbofreedman

+0

Bu durumda, yanlış gidebilecek başka iki şey düşünebilirim: ilk olarak, api.jquery.com/jQuery'de açıklandığı gibi AJAX isteğinin "crossDomain" parametresini "True" olarak ayarladığınızdan emin olun. ajax. O Django varsayılan olarak başlığındaki belirteci dahil olmayabilir, size render olduğunuz sayfada bir CSRF şablon etiketi ekleyerek değilseniz (yani, sayfa formu yoktur), bu da önemli bir etkendir. Bunu güçlendirmek için görünümünüzün 'warranty_csrf_cookie (view)' dekoratörünü kullanabilirsiniz (bkz. Https://docs.djangoproject.com/en/dev/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) – ilkahnate