2010-06-17 2 views
5

Esistono disposizioni nei binari che consentono a tutte le richieste POST AJAX dal sito di passare senza un autenticità_token?Le mie richieste jQuery AJAX POST funzionano senza inviare un token di autenticità (Rails)

Ho una chiamata ajax POST Jquery che chiama un metodo controller, ma non ho inserito alcun codice di autenticità al suo interno e tuttavia la chiamata ha esito positivo.

mio ApplicationController ha 'request_forgery_protection' e ho cambiato

config.action_controller.consider_all_requests_local 

false nei miei ambienti/development.rb

Ho anche cercato il mio codice per assicurarsi che non stavo sovraccaricare ajaxInvia l'invio di token di autenticità.

C'è qualche meccanismo in gioco che disabilita il controllo? Ora non sono sicuro che la mia protezione CSRF funzioni o meno.

Sto usando Rails 2.3.5.

Aggiornamento per chiarezza:

function voteup(url, groupid){ 
     $.ajax({ 
     type: "POST", 
     url: "/groups/" + groupid + "/submissions/voteup", 
     data: "url=" + url, 
     dataType: 'text', 
     success: function(data){ 
      var counter = "vote_" + url; 
      $('#vote_' + url.cleanify()).text(" " + data + " "); 
     } 
     }); 
    }; 

ho un link che poi ha un 'href che chiama la funzione di cui sopra:

<a href='javascript:voteup(param1,param2)'>...</a> 
+0

mi sono ricordato di rispondere a una domanda simile .. trovato qui: http://stackoverflow.com/questions/2725118/rails-request-forgery-protection-settings/2725991 # 2725991 Suppongo che dovrebbe essere perché è una richiesta locale. Non dovrebbe funzionare dire da un'app in esecuzione su una porta diversa o su un dominio diverso. Es: Se la tua app è in esecuzione su localhost: 3000 non dovresti essere in grado di eseguire un POST ajax da localhost: 3001. –

+0

Hi Shripad, Ho visto il tuo post, ma come sta succedendo? C'è qualche tipo di magia di Rails coinvolta? Guardando online, vedo ancora persone che scrivono istruzioni per inviare form_authenticity_token, quindi se è fisso, perché c'è ancora bisogno di farlo? –

+0

Questo non ha nulla a che fare con la magia di Rails. Ajax funziona senza un token di autenticità se è invocato all'interno del dominio stesso. Hai bisogno di un token di autenticità non per consentire a ajax di funzionare sul tuo dominio ma per prevenire attacchi da altri domini. Questa è la ragione principale per avere 'protect_from_forgery' nel controller dell'applicazione. Il miglior esempio di un attacco da un altro dominio è il "worm sammy di Myspace". Guarda su Capirai quindi perché hai bisogno di un token di autenticazione. –

risposta

6

Uno scenario probabile qui è che si sta utilizzando jQuery per serializzare un normale modulo Rails ... e include il campo nascosto del token di autenticazione serializzato (Rails li aggiunge a tutti i moduli).

Guardate il vostro sorgente generato per il modulo che si sta presentando ... è probabile che vedrete

<input name="authenticity_token" type="hidden" value="somethinghere...." /> 

L'altra cosa che puoi fare è controllare il registro per vedere se il campo è in authenticity_token i parametri della richiesta.

+1

Ho aggiornato la domanda con alcuni esempi di codice. I miei registri non mostrano un parametro authenticity_token inviato. –

3

Aggiungere questo nella vostra visualizzazione Layout: app/views/layouts/(something).html.erb

<% if protect_against_forgery? %> 
<script type="text/javascript" charset="utf-8"> 
    //<![CDATA[ 
    window._auth_token_name = "#{request_forgery_protection_token}"; 
    window._auth_token = "#{form_authenticity_token}"; 
    //]]> 
</script> 
<% end %> 

e nel tuo application.js:

$.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")} 
}); 

$(document).ready(function() { 
// All non-GET requests will add the authenticity token 
// If not already present in the data packet 
$("body").bind('ajaxSend', function(elm, xhr, s) { 
    if (s.type == "GET") return; 
    if (s.data && s.data.match(new RegExp("\\b" + window._auth_token_name + "="))) return; 
    if (s.data) { 
    s.data = s.data + "&"; 
    } else { 
    s.data = ""; 
    // if there was no data, $ didn't set the content-type 
    xhr.setRequestHeader("Content-Type", s.contentType); 
    } 
    s.data = s.data + encodeURIComponent(window._auth_token_name) + "=" + encodeURIComponent(window._auth_token); 
}); 

Nel vostro application_controller.rb aggiungere questo al fine di garantire IE/SAFARI ricezione corretta accettare intestazioni:

def correct_safari_and_ie_accept_headers 
    ajax_request_types = [ 'text/javascript', 'application/json', 'text/xml'] 
     request.accepts.sort!{ |x, y| ajax_request_types.include?(y.to_s) ? 1 : -1 } if request.xhr? 
end 

Ciò garantisce che l'intestazione di accettazione sia impostata su text/javascript, application/json o text/xml anziché sul valore predefinito text/html.

Ora è possibile eseguire le normali chiamate AJAX. Passerà il token di autenticazione. Assicurati inoltre di includere application.js solo dopo il tag script CDATA poiché richiede le due vars globali window._auth_token_name e window._auth_token.

Spero che questo aiuti!Saluti :)

+0

grazie per il codice, ma il mio problema è che in questo momento i miei post funzionano anche senza un token di autenticazione. –