簡體   English   中英

Codeigniter ajax CSRF問題

[英]Codeigniter ajax CSRF problem

我做了一個簡單的自動加載功能,當你在網站上向下滾動時加載內容。 但是,當我在Codeigniter中啟用CSRF保護時,似乎存在一些問題。

我沒有使用表單,所以我不知道當你滾動時我正在做我的帖子請求時如何將令牌從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期望在所有POST請求中都有TOKEN,因此當CSRF啟用時,我無法使其工作。 有什么建議?

啟用CSRF時出錯

無法加載資源:服務器響應狀態為500(內部服務器錯誤)

如果我關閉CSRF,一切都很好......

您可能想嘗試我使用過的代碼。 它很棒:

<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>

正如其他人所說 - 你必須使用AJAX請求參數發布CSFR令牌名稱及其值。 這是一個簡單的解決方案,可以自動將其附加到每個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
    });
});

如果需要,您可以在適當的位置回顯令牌名稱和哈希值。 像這樣的東西。

 echo $this->security->get_csrf_token_name()

 echo $this->security->get_csrf_hash()

或者,您可以像往常一樣使用form_open()並使用從javascript為您生成的隱藏輸入。 禁用CSRF功能是錯誤的方法。

在審查了我的情況后,我認為最好的選擇是使用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和來自w3schools的getCookie函數)將調用:

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

以前的建議很有效,但我發現使用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版本)

上面幾個答案的唯一問題是csrf令牌僅對一個請求有效,所以如果你通過ajax發出一個帖子請求並且不刷新頁面你就不會有你下一個ajax帖子的當前csrf令牌請求。 這是我的解決方案:

在您的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 =瀏覽器用於下一個ajax post請求的新csrf標記

顯然你可以用其他方式輸出它,但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 ,其中包含你在crf_token / config / config.php中找到的令牌的名稱, crf_token包含$config['csrf_token_name'] = 'csrf_token';

基本上你需要做的是從cookie中獲取預期的csrf值(默認名為'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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM