2011-09-08 71 views
7

he hecho una función de carga automática sencilla que carga el contenido cuando se desplaza hacia abajo en un sitio web. Sin embargo, parece que hay algunos problemas cuando habilito la protección CSRF en Codeigniter.CodeIgniter ajax CSRF problema

no estoy usando un formulario, por lo que no sé cómo puedo enviar la ficha de A a B cuando estoy haciendo mi solicitud posterior mientras se desplaza.

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

Desde CodeIgniter espera una señal en toda solicitud POST no puedo conseguir que esto funcione cuando CSRF i habilitado. ¿Alguna sugerencia?

error al CSRF es Habilitado

No se pudo cargar recurso: el servidor responde con un estado de 500 (Internal Server Error)

Si giro CSRF fuera, todo funciona muy bien .. .

Respuesta

10

Si lo desea, puede repetir tanto el nombre del token y el hash algún lugar apropiado. Algo como esto.

echo $this->security->get_csrf_token_name() 

y

echo $this->security->get_csrf_hash() 

O bien, puede utilizar form_open() como de costumbre y utilizar la entrada oculta que se genera para usted de su javascript. Deshabilitar la funcionalidad CSRF es la forma incorrecta de hacerlo.

0

Básicamente lo que necesita hacer es obtener el valor de csrf esperado de la cookie (denominado 'ci_csrf_token' de forma predeterminada), luego publíquelo junto con sus otros datos.

Usted tendría que modificar esta línea:

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

a:

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

posible que tenga que instalar el complemento de galletas (no estoy realmente seguro, yo uso mootools). Aquí hay más información: http://aymsystems.com/ajax-csrf-protection-codeigniter-20.

12

Usted puede intentar utilizar el código que he usado. Funciona muy bien:

<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

como otros dicen - usted tiene que colocar el nombre del token RFCE y su valor con los parámetros de la petición AJAX. Aquí hay una solución simple para agregarlo automáticamente a cada solicitud de AJAX.

Aquí es lo que he puesto en mi vista principal, lo que este código en cada página antes de cargar los otros archivos 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> 

Y aquí es una parte de un archivo JavaScript que incluyo en cada página :

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

solución muy fácil .. trabajando para mí :) Gracias @georgiar –

+0

Gracias trabajando realmente para mí –

0

sugerencias anteriores funcionan muy bien, pero en lugar de utilizar una variable que se puede aplicar en todos los datos post, les resulta más sencillo usar el establecimiento de ajax para aplicar automáticamente este símbolo para todos los envíos:

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

(trabaja con jquery-1.9.1. No estoy seguro acerca de otras versiones de jquery)

0

El único problema con algunas de las respuestas anteriores es que un token csrf solo es válido para una solicitud, por lo que si haces una solicitud por medio de ajax y no actualizas la página no tendrá el token csrf actual para su próxima solicitud posterior ajax. Esta es mi solución:

en su controlador 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 = los datos para volver al navegador

$ csrf token = nueva csrf para ser utilizado por el navegador para el próximo ajax solicitud POST

Obviamente se puede salida de esto en otras formas, pero JSON se trabaja generalmente con las llamadas ajax. También incluye este signo en toda la respuesta posterior a utilizar para la siguiente petición de entrada

Luego, en su próxima petición 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); 
    } 
}); 

recordar también que, cuando tengo csrf_token:token reemplazar con el crf_token nombre de su ficha que se encuentra en application/config/config.php en la línea que indica $config['csrf_token_name'] = 'csrf_token';

0

Habiendo examinado mi situación creo que la mejor opción es utilizar CSRF pero restablecer el token en cada intento. De lo contrario las ideas expresadas anteriormente acerca de la reutilización de la ficha de galletas que permitiría a un atacante vuelve a enviar datos cientos de veces usando la misma razón que contradice el objeto de la punta.

Como tal He creado la siguiente función:

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

Si por ejemplo un formulario de acceso basado en Ajax no - llamar a esta función en su PHP y luego en el lado javascript que recibe el fracaso (este utiliza la solución jQuery y una función de GetCookie w3schools) serían entonces sólo tiene que llamar:

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