Codeigniter ajax CSRF проблема - PullRequest
       12

Codeigniter ajax CSRF проблема

8 голосов
/ 08 сентября 2011

Я сделал простую функцию автозагрузки, которая загружает контент, когда вы прокручиваете сайт вниз.Однако, кажется, есть некоторые проблемы, когда я включаю защиту CSRF в Codeigniter.

Я не использую форму, поэтому я не знаю, как я могу отправить токен от A до B, когда я 'я делаю мой пост-запрос, когда вы прокручиваете.

Мой 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++;
                });
            }
        }
    });
}

Поскольку Codeigniter ожидает TOKEN для всех запросов POST, я не могу заставить его работать, когда CSRF включенЛюбые предложения?

Ошибка при включении CSRF

Не удалось загрузить ресурс: сервер ответил с состоянием 500 (Внутренняя ошибка сервера)

Если я выключу CSRF, все будет отлично работать ...

Ответы [ 7 ]

13 голосов
/ 22 апреля 2013

Как говорят другие - вы должны опубликовать имя токена CSFR и его значение с параметрами запроса AJAX. Вот простое решение, чтобы автоматически добавлять его к каждому запросу AJAX.

Вот что я добавляю в свой основной вид, поэтому этот код находится на каждой странице перед загрузкой других файлов 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>

А вот часть файла JavaScript, который я включаю на каждой странице:

$(function() {
    // Attach csfr data token
    $.ajaxSetup({
       data: csfrData
    });
});
13 голосов
/ 05 июня 2012

Возможно, вы захотите попробовать этот код, который я использовал. Отлично работает:

<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>
10 голосов
/ 08 сентября 2011

Если вы хотите, вы можете отобразить как имя токена, так и хеш, где это необходимо.Примерно так.

 echo $this->security->get_csrf_token_name()

и

 echo $this->security->get_csrf_hash()

Или вы можете использовать form_open () как обычно и использовать скрытый ввод, сгенерированный для вас из вашего JavaScript.Отключение функции CSRF - неправильный путь.

1 голос
/ 01 сентября 2017

Изучив мою ситуацию, я считаю, что лучше всего использовать CSRF, но сбрасывать токен при каждой попытке.В противном случае идеи, высказанные ранее о повторном использовании токена cookie, позволили бы злоумышленнику повторно отправлять данные сотни раз с использованием того же токена, который побеждает объект точки.

Таким образом, я создал следующую функцию:

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

Если, например, форма входа в систему на основе ajax не работает - вызовите эту функцию в вашем PHP, а затем на стороне javascript, которая получает ошибку (это решение использует Jquery и функцию getCookie из w3schools), затем просто вызовет:

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

0 голосов
/ 11 июня 2016

Единственная проблема с несколькими из приведенных выше ответов заключается в том, что токен csrf действителен только для одного запроса, поэтому, если вы отправляете пост-запрос через ajax и не обновляете страницу, у вас не будет текущего токена csrf для вашего запроса. следующий запрос ajax. Это мое решение:

В вашем контроллере 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 = данные для возврата в браузер

$ csrf = новый токен csrf, который будет использоваться браузером для следующего пост-запроса ajax

Очевидно, что вы можете выводить это другими способами, но JSON используется в основном с вызовами ajax. Также включайте этот токен в каждый пост-ответ, который будет использоваться для следующего пост-запроса

Тогда в вашем следующем 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 );
    }
});

Также помните, что там, где у меня есть csrf_token:token, замените crf_token именем вашего токена, найденного в файле application / config / config.php, в котором указано $config['csrf_token_name'] = 'csrf_token';

0 голосов
/ 21 декабря 2014

Предыдущие предложения прекрасно работают, но вместо того, чтобы использовать переменную, которую вы можете применять в каждом посте данных, я считаю, что проще использовать ajax-параметр для автоматического применения этого токена к каждому посту:

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

(работает с jquery-1.9.1. Я не уверен насчет других jquery-версий)

0 голосов
/ 25 января 2012

По сути, вам нужно получить ожидаемое значение csrf из файла cookie (по умолчанию называемое «ci_csrf_token»), а затем опубликовать его вместе с другими вашими данными.

Вам необходимо изменить эту строку:

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

до:

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

Возможно, нужно установить аддон cookie (я не совсем уверен; я использую mootools). Вот больше информации: http://aymsystems.com/ajax-csrf-protection-codeigniter-20.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...