2011-09-08 5 views
7

Ho creato una semplice funzione di caricamento automatico che carica il contenuto quando si scorre verso il basso su un sito Web. Tuttavia, sembra che ci siano alcuni problemi quando abilito la protezione CSRF in Codeigniter.Codeigniter ajax CSRF problem

Non sto utilizzando un modulo, quindi non so come posso inviare il token da A a B quando sto facendo la mia richiesta di post mentre scorri.

mio JavaScript

if (location.href == baseurl) { 
    $(window).scroll(function(){ 
     if ($(window).scrollTop() > $('body').height()/2) { 
      if(doScroll == 1) { 
       $.post(baseurl + 'ajax/images',{'id' : ID}, function(data) { 
        $("#wrapper_content").append(data); 
        if(data == 'Det finnes ikke flere bilder i databasen, WTF!? Send inn forslag ASAP!') { 
         doScroll = 0; 
        } 
        ID++; 
       }); 
      } 
     } 
    }); 
} 

Dal Codeigniter aspetta un gettone su tutti i richiesta POST non posso arrivare a questo lavoro quando CSRF ho attivato. Eventuali suggerimenti?

errore quando CSRF è abilitata

Impossibile caricare risorsa: il server ha risposto con uno stato di 500 (Internal Server Error)

se giro CSRF off, tutto funziona alla grande ..

risposta

10

Se lo si desidera, è possibile richiamare sia il nome del token che l'hash in un punto appropriato. Qualcosa come questo.

echo $this->security->get_csrf_token_name() 

e

echo $this->security->get_csrf_hash() 

Oppure, si potrebbe utilizzare Form_Open() come al solito e utilizzare l'ingresso nascosto che viene generato per voi dal vostro javascript. Disabilitare la funzionalità CSRF è la strada sbagliata.

0

Fondamentalmente quello che devi fare è ottenere il valore csrf atteso dal cookie (chiamato 'ci_csrf_token' di default), quindi pubblicarlo insieme agli altri dati.

Si avrebbe bisogno di modificare questa linea:

$.post(baseurl + 'ajax/images',{'id' : ID}, function(data) { 

a:

$.post(baseurl + 'ajax/images',{'id' : ID,'ci_csrf_token' : $.cookie('ci_csrf_token')}, function(data) { 

potrebbe essere necessario installare l'addon biscotto (non sono davvero sicuro; io uso MooTools). Ecco ulteriori informazioni: http://aymsystems.com/ajax-csrf-protection-codeigniter-20.

12

Ti piacerebbe provare questo codice che ho usato. E le grandi opere:

<script type="text/javascript"> 
$(function(){ 
    $('.answerlist').each(function(e){ 

    $(this).click(function(){ 

    var valrad = $("input[@name=answer]:checked").val(); 


    var post_data = { 
     'ansid': valrad, 
     '<?php echo $this->security->get_csrf_token_name(); ?>' : '<?php echo $this->security->get_csrf_hash(); ?>' 
    }; 

     $.ajax({ 
       type: "POST", 
       url: "<?php echo base_url(); ?>online/checkanswer", 
       data: post_data, 
       success: function(msg){ 
        /// do something 
       } 
      }); 

    }); 

    }); 


}); 


</script> 
12

Come altri dire - si deve inviare il nome del token Cecoslovacchia e il suo valore con i parametri di richiesta AJAX. Ecco una semplice soluzione per aggiungerla automaticamente ad ogni richiesta AJAX.

Ecco quello che ho messo sul mio punto di vista principale, per cui questo codice è in ogni pagina prima di caricare gli altri file javascript:

<script> 
    var csfrData = {}; 
    csfrData['<?php echo $this->security->get_csrf_token_name(); ?>'] 
         = '<?php echo $this->security->get_csrf_hash(); ?>'; 
    </script> 
    <!-- ... include other javascript files --> 
    </body> 
</html> 

E qui è una parte di un file JavaScript che includo in ogni pagina :

$(function() { 
    // Attach csfr data token 
    $.ajaxSetup({ 
     data: csfrData 
    }); 
}); 
+0

molto facile soluzione .. lavora per me :) Grazie @georgiar –

+0

Grazie davvero lavorare per me –

0

precedenti suggerimenti grande lavoro, ma invece di utilizzare una variabile che è possibile applicare in ogni data-post, ho trovato più semplice utilizzare l'ajax-impostazione per applicare automaticamente questo token per ogni post:

$(document).ajaxSend(function(elm, xhr, s){ 
     if(s.data){ 
      s.data += '&'; 
     } 
     s.data += '<?php echo $this->security->get_csrf_token_name(); ?>=<?php echo $this->security->get_csrf_hash(); ?>'; 
    }); 

(funziona con jquery-1.9.1. Non sono sicuro di altre versioni jquery)

0

L'unico problema con alcune delle risposte precedenti è che un token csrf è valido solo per una richiesta, quindi se si effettua una richiesta di posta via ajax e non si aggiorna nella pagina non avrai il token csrf corrente per la tua successiva richiesta di posta ajax. Questa è la mia soluzione:

nel controller CodeIgniter:

$data = array('data'=> 'data to send back to browser'); 
$csrf = $this->security->get_csrf_hash(); 
$this->output 
    ->set_content_type('application/json') 
    ->set_output(json_encode(array('data' => $data, 'csrf' => $csrf))); 

$ data = i dati da restituire al browser

$ csrf = new CSRF token per essere utilizzato dal browser per il prossimo ajax invia richiesta

Ovviamente è possibile eseguire l'output in altri modi, ma JSON viene utilizzato principalmente con chiamate Ajax. Anche includere questo token in ogni risposta post da utilizzare per la richiesta successiva posta

Poi, nel tuo prossimo richiesta AJAX (javascript):

var token = data.csrf; 

$.ajax({ 
    url: '/next/ajax/request/url', 
    type: 'POST', 
    data: { new_data: 'new data to send via post', csrf_token:token }, 
    cache: false, 
    success: function(data, textStatus, jqXHR) { 
     // Get new csrf token for next ajax post 
     var new_csrf_token = data.csrf  
     //Do something with data returned from post request 
    }, 
    error: function(jqXHR, textStatus, errorThrown) { 
     // Handle errors here 
     console.log('ERRORS: ' + textStatus + ' - ' + errorThrown); 
    } 
}); 

Ricordo anche che in cui ho csrf_token:token sostituire crf_token con la nome del token si trovano in application/config/config.php on line che indica $config['csrf_token_name'] = 'csrf_token';

0

Dopo aver esaminato la mia situazione credo che la soluzione migliore è quella di utilizzare CSRF ma ripristinare il gettone su ogni tentativo. In caso contrario, le idee espresse in precedenza sul riutilizzo del token cookie consentirebbero a un utente malintenzionato di inviare nuovamente i dati centinaia di volte utilizzando lo stesso token che sconfigge l'oggetto del punto.

Come tale ho creato la seguente funzione:

public function resetCSRF(){  

    $this->security = null; 

    $_COOKIE[$this->config->item('csrf_cookie_name')] = null; 

    load_class('Security', 'core'); 

    $this->security->csrf_set_cookie(); 

return $this->security->get_csrf_hash(); 
} 

Se ad esempio un modulo di login basato su Ajax non riesce - chiamare questa funzione in PHP e poi sul lato javascript che riceve il fallimento (Questa soluzione utilizza jquery e una funzione getCookie da w3schools) sarebbero quindi semplicemente chiamare:

$('input[name="csrf_test_name"]').val(getCookie('csrf_cookie_name'));