2014-09-25 53 views
3

我遇到了一些奇怪的問題。我正在編寫一個簡單的小應用程序,並需要將一些內容發回django視圖。我在這裏以下指南:https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/設置阿賈克斯頭和在我的js以下代碼:Django csrf_token在chrome中爲null

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'); 
console.log(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); 
     } 
    } 
}); 

我有一個形式,我的HTML的代碼:

<form onsubmit="return false;"> 
       {% csrf_token %} 
       <input type="text" id="map-id-input"/> 
       <button id="map-id-btn" class='btn btn-default custom-btn'> 
        Go 
       </button> 
      </form> 

我也有JS代碼片段,上面的按鈕被點擊時運行:

$(function() { 
$("#map-id-btn").click(function() { 
    checkMapID(); 
}) 
}) 

function checkMapID() { 
    var mapId = $("#map-id-input").val(); 
    $.ajax({ 
     url: "check_map_id/", 
     type: "POST", 
     dataType: "json", 
     data: { 
      csrfmiddlewaretoken: csrftoken, 
      map_id: mapId, 
     }, 
     success: function(status_dict) { 
      if (status_dict.status === 1) { 
       $("#status").html("Valid map ID <br> Loading Data...") 
       window.location = status_dict.url; 
      } 
      else { 
       $("#status").html("Invalid map ID. Please try again, or contact ...") 
      } 
     }, 
     error: function(result) { 
      console.log(result) 
     } 
    }); 
} 

我所有的Javacript是在一個文件中,放在我的模板的頂部。

映入URL中的視圖「check_map_id /」是:

@ensure_csrf_cookie 
def check_map_id(request): 
map_id = request.POST['map_id'] 

if map_id not in GEOJSON_LOOKUP.keys(): 
    status = json.dumps({ 
     'status': 0, 
     'url': '', 
    }) 
    return HttpResponse(status, content_type="application/json") 
else: 
    status = json.dumps({ 
     'status': 1, 
     'url': reverse('map', args=(map_id,)), 
    }) 
    return HttpResponse(status, content_type="application/json") 

現在,當我使用的Firefox在我的本地機器上運行的應用程序,我得到一個有效的CSRF令牌被打印到控制檯。如果我在Chrome或IE中啓動本地計算機上的應用程序,則會打印出null。現場網站也迴應了同樣的行爲。我正在使用linux(mint),奇怪的是,如果我在firefox上啓動應用程序在Windows機器上,它也會在Firefox中返回null。有什麼奇怪的事情發生在這裏!有任何想法嗎?我似乎正在做django文檔建議的內容。

更新: 我在我的索引視圖中添加了@ensure_csrf_cookie,現在我在本地機器上的兩個broswers上都獲得了一個令牌。但是,該代碼不適用於我的實時服務器。如果我在我的js中查找一些隨機console.log,它會顯示在活動服務器上,以便代碼正在運行。我真的很茫然。

UPDATE2: 因此,我確定問題在於我的現場網站上沒有設置document.cookie屬性。我猜csrftoken =「...」cookie是由django設置的。它似乎將它設置在我的本地機器上,而不是在我的現場網站上。代碼完全相同:/。這到底是怎麼回事?!

回答

4

好的。我發現了這個問題!這是一個簡單的情況,首先不實際發送csrf標記到html頁面。我專注於ajax調用,這實際上是正確的。

我改變了實際呈現違規的形式是頁面是視圖:

@ensure_csrf_cookie 
def index(request): 
    context = RequestContext(request) 
    return render_to_response('vis_it_app/index.html', context) 

這裏的關鍵是「RequestContext的」在默認情況下,發送捷克斯洛伐克令牌爲好。這是一個使命......

所以總結。做這個工作。

  1. 確保CSRF令牌使用的RequestContext和@ensure_csrf_cookie

  2. 確保真正被髮送到你打算使用它的頁面{%csrf_token%}在您的形式某處

  3. 在此處添加AJAX特定代碼:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax到您的頁面JavaScript

  4. 確保您通過以下方式將中間件令牌發送回ajax數據:

    $阿賈克斯({ 網址: 「... 」 類型: 「POST」, 數據類型:「 ...」, 數據:{ csrfmiddlewaretoken:csrftoken, ... },

而且應該這樣做。