2011-09-08 20 views
7

Wykonałem prostą funkcję automatycznego ładowania ładującą zawartość po przewinięciu strony internetowej. Jednak wydaje się, że jest kilka problemów, gdy włączam ochronę CSRF w Codeigniter.Codeigniter ajax Problem CSRF

Nie używam formularza, więc nie wiem, w jaki sposób mogę wysłać token od A do B, gdy wykonuję moją prośbę o podanie podczas przewijania.

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

Od CodeIgniter spodziewa żeton na wszystkie żądania POST nie mogę uzyskać to do pracy, gdy CSRF i włączona. Jakieś sugestie?

Błąd podczas CSRF jest Włączone

Nie udało się załadować zasób: serwer odpowiedział ze statusem 500 (Internal Server Error)

Jeśli mogę włączyć CSRF off, wszystko działa świetnie ..

Odpowiedz

10

Jeśli chcesz, możesz wywołać echo zarówno nazwy tokena, jak i skrótu. Coś takiego.

echo $this->security->get_csrf_token_name() 

i

echo $this->security->get_csrf_hash() 

Albo można użyć form_open() jak zwykle i wykorzystywać ukryte wejście, który jest generowany dla ciebie z javascript. Wyłączenie funkcji CSRF jest niewłaściwą drogą.

0

Zasadniczo należy uzyskać oczekiwaną wartość csrf z pliku cookie (domyślnie nazywanego "ci_csrf_token"), a następnie opublikować wraz z innymi danymi.

Trzeba by zmodyfikować ten wiersz:

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

do:

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

może trzeba zainstalować dodatek cookies (nie jestem pewien; używam Mootools). Oto więcej informacji: http://aymsystems.com/ajax-csrf-protection-codeigniter-20.

12

Możesz spróbować użyć tego kodu, którego użyłem. Działa świetnie:

<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

Jak inni mówią - trzeba pisać Czecho-Słowacji symboliczną nazwę i swoją wartość z parametrów żądania AJAX. Oto proste rozwiązanie do automatycznego dołączania do każdego żądania AJAX.

Oto co mogę umieścić na moim głównym widoku, więc ten kod jest na każdej stronie przed załadowaniem inne pliki 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> 

I tu jest częścią pliku javascript, że to na każdej stronie :

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

bardzo proste rozwiązanie działa na mnie .. :) Dzięki @georgiar –

+0

Dzięki naprawdę działa dla mnie –

0

Wcześniejsze sugestie działa świetnie, ale zamiast używać zmiennych, które można zastosować w każdym danych post uważam, że to prostsze używać ajax ustawienie, aby automatycznie zastosować ten token do każdego postu:

$(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(); ?>'; 
    }); 

(działa z jquery-1.9.1. Nie mam pewności co do innych wersji jquery)

0

Jedyny problem z kilkoma z powyższych odpowiedzi polega na tym, że token csrf jest ważny tylko na jedno żądanie, więc jeśli wysyłasz żądanie przez ajax i nie odświeżasz strona, na której nie będziesz mieć aktualnego tokena csrf dla następnej prośby o dodanie do ajaxowej. To jest moje rozwiązanie:

W swojej CodeIgniter Kontroler:

$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 = dane, aby powrócić do przeglądarki

$ csrf = new csrf żeton być stosowany przez przeglądarkę kolejnego ajax żądanie posta

Oczywiście możesz wypisać to na inne sposoby, ale JSON jest używany głównie z wywołaniami ajax. Także ten żeton w każdym poście odpowiedzi do wykorzystania w następnym poście życzenie

Potem w następnym żądanie 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); 
    } 
}); 

Należy również pamiętać, że jeżeli mam csrf_token:token zastąpić crf_token z nazwa tokena znalezionego w application/config/config.php on line, które stwierdza $config['csrf_token_name'] = 'csrf_token';

0

po rozpatrzeniu mojej sytuacji uważam, że najlepszym rozwiązaniem jest użycie CSRF ale zresetować token po każdej próbie. W przeciwnym razie uprzednio wyrażone pomysły dotyczące ponownego użycia tokena cookie umożliwiłyby osobie atakującej ponowne przesłanie danych setki razy przy użyciu tego samego tokena, który pokonał obiekt punktu.

Jako takie Stworzyłem następującą funkcję:

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

Jeśli na przykład ajax oparty formularz logowania nie powiedzie - wywołać tę funkcję w PHP, a następnie na stronie javascript, który odbiera awarii (to rozwiązanie wykorzystuje jQuery i funkcją GetCookie z w3schools) będzie po prostu zadzwonić:

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

Powiązane problemy