2011-10-19 18 views

Respuesta

13

Debe establecer un encabezado HTTP personalizado, X-CSRFToken, en su solicitud AJAX. Ver: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

Si ya ha seguido ese consejo, debería estar funcionando. Use algo como Firebug para controlar la solicitud que se envía e inspeccione los encabezados para asegurarse de que el encabezado personalizado realmente se está pasando. Si no es así, verifique su implementación nuevamente para asegurarse de que lo hizo tal como lo describen los documentos.

También tenga en cuenta:

Debido a un error introducido en jQuery 1.5, el ejemplo anterior no funcionará correctamente en esa versión. Asegúrese de ejecutar al menos jQuery 1.5.1.

+0

Gracias por la punta con Firebug. Eso lo hizo. Podría ver el Token en la Cookie y el que está en la solicitud. Descubrí que el problema no estaba en esta parte de mi aplicación. Para responder a mi pregunta: El campo de etiqueta de plantilla no es necesario debido a esta función Pre-AJAX. ¿Derecha? –

+1

Sí, y si entiendo los documentos correctamente, Django está superando la etiqueta de la plantilla por completo, prefiriendo las cookies para manejar el token CSRF. –

0

Un token CSRF se asigna a cada sesión (es decir, cada vez que se conecte). Entonces, antes de desear obtener algunos datos ingresados ​​por el usuario y enviarlos como una llamada ajax a alguna función que esté protegida por el decorador csrf_protect, intente encontrar las funciones que se están llamando antes de obtener estos datos del usuario. P.ej. se debe representar una plantilla en la que el usuario ingresa datos. Esa plantilla está siendo renderizada por alguna función. En esta función, puede obtener el token csrf de la siguiente manera: csrf = request.COOKIES ['csrftoken'] Ahora pase este valor csrf en el diccionario de contexto con el que se está representando la plantilla en cuestión. Ahora en esa plantilla, escriba esta línea: ahora en su función javascript, antes de hacer una solicitud ajax, escriba esto: var csrf = $ ('# csrf'). Val() esto seleccionará el valor del token pasado a la plantilla y lo almacenará en variable csrf. Ahora, al hacer una llamada ajax, en sus datos de publicación, pase este valor también: "csrfmiddlewaretoken": csrf

Esto funcionará incluso si no está implementando formularios django.

De hecho, la lógica aquí es: necesita un token que puede obtener de la solicitud. Así que solo necesita averiguar la función a la que se llama inmediatamente después de iniciar sesión. Una vez que tenga este token, realice otra llamada ajax para obtenerla o páselo a alguna plantilla a la que pueda acceder su ajax.

0

Hay dos pasos para configurar el token CSRF, si desea publicar sin un formulario.

1) Obtenga csrftoken de Cookie.

2) Una vez que tenga el csrftoken, debe configurar el encabezado con csrftoken (antes de PUBLICAR los datos).


1) Obtenga csrftoken de Cookie.

// Function to GET csrftoken from Cookie 
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'); 

2) Una vez que tenga la csrftoken, se debe establecer la cabecera con csrftoken (antes de publicar los datos).

function csrfSafeMethod(method) { 
    // these HTTP methods do not require CSRF protection 
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); 
} 

// Function to set Request Header with `CSRFTOKEN` 
function setRequestHeader(){ 
    $.ajaxSetup({ 
     beforeSend: function(xhr, settings) { 
      if (!csrfSafeMethod(settings.type) && !this.crossDomain) { 
       xhr.setRequestHeader("X-CSRFToken", csrftoken); 
      } 
     } 
    }); 
} 

function postSomeData() { 
    ..... 
    setRequestHeader(); 

    $.ajax({ 
     dataType: 'json', 
     type: 'POST', 
     url: "/url-of-some-api/", 
     data: data, 
     success: function() { 
      alert('success'); 
     }, 
     error: function() { 
      alert('error'); 
     } 
    }); 

}