2015-05-10 19 views
16

Sto lavorando su un'applicazione a singola pagina e sto utilizzando Laravel 5 per il servizio web.Come includere il token CSRF nelle intestazioni nella richiesta di caricamento Dropzone?

Tutte le forme sono presentati in modo asincrono e io uso un beforeSend su di loro per collegare il token CSRF, che prendo dalla meta tag in questo modo:

$.ajax({ 
    url: '/whatever/route', 
    type: 'POST', 
    dataType: 'JSON', 
    data: $('form#whatever-form').serialize(), 
    beforeSend: function(request) { 
     return request.setRequestHeader('X-CSRF-Token', $("meta[name='token']").attr('content')); 
    }, 
    success: function(response){ 
     rivets.bind($('#whateverTag'), {whateverData: response}); 
    }, 
    error: function(response){ 
    } 
}); 

Tutte le mie forme funzionano bene, ma caricati zona di lancio non lo fa. Mi restituisce un'eccezione TokenMismatchException. Ecco il mio codice zona di lancio per aggiornare la foto del profilo: mettere

$("#mydropzone").dropzone({ 
    url: "/profile/update-photo", 
    addRemoveLinks : true, 
    maxFilesize: 5, 
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>', 
    dictResponseError: 'Error uploading file!' 
}); 

Ho provato il beforeSend anche qui:

$("#mydropzone").dropzone({ 
    url: "/profile/update-photo", 
    addRemoveLinks : true, 
    maxFilesize: 5, 
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>', 
    dictResponseError: 'Error uploading file!', 
    beforeSend: function(request) { 
     return request.setRequestHeader('X-CSRF-Token', $("meta[name='token']").attr('content')); 
    }, 
}); 

Ho anche provato a mettere un ajaxSetup globale nel mio file principale in questo modo :

$.ajaxSetup({ 
    headers: { 
     'X-CSRF-TOKEN': $('meta[name="token"]').attr('content') 
    } 
}); 

Non funziona ancora. Che cosa sto facendo di sbagliato? Come posso passare il token CSRF nell'intestazione con il dropzone upload in modo da non ottenere un'eccezione?

+0

Hai scritto "Dropbox", ma non lo faccio vedi qualsiasi cosa nella tua domanda relativa a Dropbox. Forse intendevi dire Dropzone? Per ora rimuoverò il tag Dropbox. – smarx

+0

Grazie per averlo portato a mia conoscenza. Era così stupido da parte mia. – Rohan

risposta

22

Va bene così questo codice sta lavorando bene ora:

$("#mydropzone").dropzone({ 
    url: "/profile/update-photo", 
    addRemoveLinks : true, 
    maxFilesize: 5, 
    dictDefaultMessage: '<span class="text-center"><span class="font-lg visible-xs-block visible-sm-block visible-lg-block"><span class="font-lg"><i class="fa fa-caret-right text-danger"></i> Drop files <span class="font-xs">to upload</span></span><span>&nbsp&nbsp<h4 class="display-inline"> (Or Click)</h4></span>', 
    dictResponseError: 'Error uploading file!', 
    headers: { 
     'X-CSRFToken': $('meta[name="token"]').attr('content') 
    } 
}); 

Quindi, in pratica avevo bisogno di aggiungere il X-CSRFToken nell'intestazione della richiesta Dropzone. Funziona come un fascino ora.

+0

Documentazione sul sito Dropzone: http://www.dropzonejs.com/#config-headers – sameers

+3

volevo solo chiarire un po 'la denominazione, l'installazione di Laravel predefinita sta cercando '' X-CSRF-TOKEN ': $ ('meta [name = "csrf-token"]'). attr ('contenuto') '. https://laravel.com/docs/5.5/csrf#csrf-x-csrf-token –

4

È possibile aggiungere token csrf per ogni richiesta jjery javery all'interno dell'applicazione con questo codice.

$.ajaxSetup({ 
    headers: { 
     'X-CSRF-Token': $('meta[name="_token"]').attr('content') 
    } 
}); 
+2

Per [il documento jQuery su questa funzione] (https://api.jquery.com/jquery.ajaxsetup/), "il suo l'uso non è raccomandato. " Inoltre, penso che questo potrebbe influenzare solo le chiamate AJAX fatte tramite '$ .ajax()' nella libreria jQuery? – sameers

+0

@sameers è corretto. – Erutan409

1

Credo che il modo migliore per gestire questa situazione è di impostare di default per tutti i post Ajax (con jQuery) come Secondo la documentazione Django

https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

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)); 
} 

function sameOrigin(url) { 
    // test that a given url is a same-origin URL 
    // url could be relative or scheme relative or absolute 
    var host = document.location.host; // host + port 
    var protocol = document.location.protocol; 
    var sr_origin = '//' + host; 
    var origin = protocol + sr_origin; 
    // Allow absolute or scheme relative URLs to same origin 
    return (url == origin || url.slice(0, origin.length + 1) == origin + '/') || 
     (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') || 
     // or any other URL that isn't scheme relative or absolute i.e relative. 
     !(/^(\/\/|http:|https:).*/.test(url)); 
} 

$.ajaxSetup({ 
    beforeSend: function(xhr, settings) { 
     if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) { 
      // Send the token to same-origin, relative URLs only. 
      // Send the token only if the method warrants CSRF protection 
      // Using the CSRFToken value acquired earlier 
      xhr.setRequestHeader("X-CSRFToken", csrftoken); 
     } 
    } 
}); 

Nel tuo esempio , hai un errore di battitura quando lo aggiungi al post di azoax di Dropzone.js.

'X-CSRFToken'

dovrebbero essere

'X-CSRFToken'

+0

Impostandolo su post ajax predefiniti crea un altro problema che ho riscontrato in seguito. Stavo cercando di consumare un servizio di terze parti e mi sono bloccato perché non riuscivo a capire quale fosse l'errore. In seguito mi sono reso conto che le impostazioni predefinite inviavano il token CSRF a terze parti e causava un problema. :) – Rohan

+0

Buon punto e vale la pena ricordare! Direi una chiamata di giudizio. Se nel tuo codice ci sono molte più chiamate ajax locali allora forse fare un'eccezione per le chiamate remote avrebbe più senso, o inverso quando è vero il contrario. Qualunque cosa alla fine produce meno lavoro. Saluti! – jb0t

0

possiamo impostare CSRF token richiesta di intestazione.

xhr = open("POST",logURL,true); 
 
     //Set CSRF token in request header for prevent CSRF attack. 
 
xhr.setRequestHeader(CSRFHeaderName, CSRFToken);

0

per chi utilizza di default l'installazione laravel:

window.Laravel = {!! json_encode([ 
    'csrfToken' => csrf_token(), 
]) !!}; 

Dropzone.options.attachments = { 
    url: 'upload', 
    headers: { 
     'X-CSRF-TOKEN': Laravel.csrfToken 
    } 
} 
1

Questo funziona anche abbastanza bene:

$("#mydropzone").dropzone({ 
    url: "/profile/update-photo", 
    addRemoveLinks : true, 
    maxFilesize: 5, 
    dictResponseError: 'Error uploading file!', 
    headers: { 
    'X-CSRF-Token': $('input[name="authenticity_token"]').val() 
    } 
});