Sto lavorando a un progetto che utilizza il framework Django REST come backend (diciamo allo api.somecompany.com
ma ha un frontend React.js (allo www.somecompany.com
) non servite da Django che fa richieste AJAX.Come recuperare/fornire un token CSRF a/da Django come API
non posso, quindi, utilizzare il metodo tradizionale di Django di avere il modello includono il token CSRF in questo modo <form action="." method="post">{% csrf_token %}
posso fare una richiesta al api-auth\login\
url di Django REST quadro , che restituirà questa intestazione: Set-Cookie:csrftoken=tjQfRZXWW4GtnWfe5fhTYor7uWnAYqhz; expires=Mon, 01-Aug-2016 16:32:10 GMT; Max-Age=31449600; Path=/
- ma non riesco quindi a recuperare questo cookie per rispedire indietro con le mie richieste AJAX h X-CSRFToken
(la mia comprensione è del sottodominio separato) e non sembra essere inclusa automaticamente.
Ecco il mio codice rilevante:
// 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'));
}
}
});
Come la pagina viene caricata Io chiamo questo per assicurarsi che ho un token:
$.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)
});
Questo non è esattamente pulito ma non ho provato il concetto a me stesso ancora.
Qual è il modo "corretto" di autenticazione/protezione contro CSRF quando il frontend e il backend si trovano su porte/domini diversi?
Penso di averlo già coperto - la mia richiesta non ha esito negativo per motivi CORS. Il mio problema, per quanto posso dire, è che la mia prima richiesta (quella di 'OPTIONS') non sta impostando il cookie 'csrftoken', quindi non posso leggerlo per aggiungerlo come intestazione, o farlo inviare automaticamente con una successiva richiesta. Effettuare direttamente una richiesta (non usando AJAX) imposta i cookie correttamente. C'è qualcosa che impedisce il settaggio del cookie? – jimbofreedman
In questo caso, posso pensare ad altre due cose che potrebbero andare storte: in primo luogo, assicurati di impostare il parametro 'crossDomain' della richiesta AJAX su' True' come descritto in api.jquery.com/jQuery. ajax. È anche probabile che, se non includi un tag modello CSRF sulla pagina che stai rendendo (cioè la pagina non ha forma), Django potrebbe non includere il token nell'intestazione per impostazione predefinita. Puoi usare il decoratore 'ensure_csrf_cookie (view)' attorno alla tua vista per forzarlo (vedi https://docs.djangoproject.com/en/dev/ref/csrf/#django.views.decorators.csrf.ensure_csrf_cookie) – ilkahnate