web-dev-qa-db-ja.com

Codeigniter CSRFは1回だけのajaxリクエストに対して有効です

JQueryの変更イベントでサーバーに画像をアップロードしたいのですが、codeigniter csrfを使用すると、画像を一度だけアップロードできます。複数のリクエストに対してajaxを使用して画像をアップロードするにはどうすればよいですか?これを設定するときは注意してください

config['csrf_protection'] = FALSE;

その後、複数のリクエストjQuery onchangeイベントを送信できますが、csrf_protectionがfalseになるとcsrfの利点はないと思います。したがって、質問は、csrf_protectionが有効なときにajaxを使用して複数のリクエストを送信する方法です。私のjqueryコードは次のとおりです

$("#avatar").change(function(){
    var link = $("#avatar").val();     
    $.ajax({
        url : "<?php echo base_url('main/test'); ?>",
        type: 'post',
        data: {'<?php echo $this->security->get_csrf_token_name(); ?>':'<?php echo $this->security->get_csrf_hash(); ?>',"id":"hello","link":link},            
        success : function(data)
        {   
            alert(data);
        }  
    });
});
10
romio

私の意見では、リクエストごとにcsrfトークンを再作成する必要があります

このコード例を試してください...

Js機能について

var csrfName = '<?php echo $this->security->get_csrf_token_name(); ?>',
    csrfHash = '<?php echo $this->security->get_csrf_hash(); ?>';
("#avatar").change(function(){
    var link = $("#avatar").val();

    var dataJson = { [csrfName]: csrfHash, id: "hello", link: link };

    $.ajax({
        url : "<?php echo base_url('main/test'); ?>",
        type: 'post',
        data: dataJson,            
        success : function(data)
        {   
            csrfName = data.csrfName;
            csrfHash = data.csrfHash;
            alert(data.message);
        }  
    });
});

そしてコントローラー用

public function test() { 
    $config['upload_path'] = './uploads/'; 
    $config['allowed_types'] = 'gif|jpg|png'; 
    $config['max_size'] = 500; 
    $config['max_width'] = 260; 
    $config['max_height'] = 260; 

    $reponse = array(
                'csrfName' => $this->security->get_csrf_token_name(),
                'csrfHash' => $this->security->get_csrf_hash()
                )

    $this->load->library('upload', $config); 
    if (!$this->upload->do_upload('link')) { 
        $reponse['message'] = "error"; 
    } 
    else { 
        $data = array('upload_data' => $this->upload->data()); 
        $image_name = $data['upload_data']['file_name']; 
        $reponse['message'] = $image_name; 
    } 

    echo json_encode($reponse);
}

私に知らせて、幸運を

注:誰かが質問にさらにデータを投稿するように頼んだら、コメントや回答として投稿しないでください。質問自体を編集して、内容を追加する方が良いです

15
Edu

これはconfig.phpで設定できます

$config['csrf_regenerate'] = FALSE;

したがって、csrf保護はすべてのセッション時間中有効であり、問​​題を解決します。 $config['csrf_regenerate'] = true;を設定すると、CIはリクエストごとに新しいcsrfトークンを生成するため、古いcsrfトークンは新しく生成されたcsrfトークンと一致しません

5
Brian85

あなたがする必要があるのは、AJAXレスポンスでCSRFトークンをリロードすることです。それはとても簡単です!

1
Brian85

$config['csrf_regenerate'] = TRUE;

自動生成をtrueにすると、より安全になります。同様の場合、最初の要求でcsrfが期限切れになる場合。私が実装したもの

$(document).ajaxComplete(function (event, xhr, settings) {
 let response = xhr.responseText,
 let obj = JSON.parse(response),
 let csrfData = obj.csrf;
 document.querySelector('input[name="' + csrfData.name + '"]').value = csrfData.hash; 
}); //Also here you can update any other non input element    

すべてのajax応答で、最新のcsrfデータが現在のcsrfデータに置き換えられるcsrfデータを渡します

リクエストからのサンプル応答

{ 
csrf : {
  name : 'csrf_name',
  hash : 'qw76sd7s6f78sdfs8dfs9df8cx9'
 }
}

すべてのajaxリクエストでcsrfトークンを更新します。また、マルチタブ環境で作業している場合は、この方法を選択しないでください

1

これをすべてのページにロードされるjsファイルに追加します(これをjquery.jsの最後に配置します)

    $.ajaxSetup({
        beforeSend:function(jqXHR, Obj){
            var value = "; " + document.cookie;
            var parts = value.split("; csrf_cookie_name=");
            if(parts.length == 2)   
            Obj.data += '&csrf_token='+parts.pop().split(";").shift();
        }
    });

(すべてのajaxリクエストでは、送信する空のデータを保持できないことに注意してください)

config.phpで定義されている上部の「csrf_cookie_name」

$config['csrf_cookie_name'] = 'csrf_cookie_name';
0

リクエストを行うたびに、csrf_token[〜#〜] ci [〜#〜]によって更新されます。 [〜#〜] csrf [〜#〜]が一度しか機能しないのはそのためです。そのため、リクエストを行うたびに、csrf_tokenも更新する必要があります。これを行うことでこの問題を解決します。

Conrollerこのコードを使用して更新されたcsrfを取得します

public function update_csrf()
{
  $data['csrf_hash'] = $this->security->get_csrf_hash();
  echo json_encode($data);
}

[〜#〜] ajax [〜#〜]yourの古い値を置き換えるcsrf = name="csrf_token_name"

var jqXHR = $.ajax({
            url: $(this).attr('action'),
            type: 'POST',
            data: $(this).serialize(),
            dataType: 'json',
        })
        jqXHR.done(function(response) {
            $('input[name=csrf_token_name]').val(response.csrf_hash); //update the csrf to the form 
        })
        jqXHR.fail(function(jqXHR, textStatus, errorThrown) {
            console.log(jqXHR);
            console.log(textStatus);
            console.log(errorThrown);
        });

重要 !: dataType: 'json'を使用

したがって、リクエストが成功するたびに、csrf_tokenも更新され、403(Forbidden)errorから解放されます。

0
curiosity

私のコードのように試してください。その動作私のアプリケーション

あなたのビューファイル

$token_name = $this->security->get_csrf_token_name();
$token_hash = $this->security->get_csrf_hash();

<input type="text" id="search-text" name="parent_name" placeholder="Search" value=""  >
<input type="hidden" id="csrf" name="<?php echo $token_name; ?>" value="<?php echo $token_hash; ?>" />

以下のようなjquery postメソッドを設定した後

// Get Keyup 
jQuery( "#search-text").keyup(function() {
    // Get Data 
    var val       = jQuery("#search-text").val();
    var hashValue = jQuery('#csrf').val();

    // Get jquery post for ajax task
    jQuery.post( 
        '<?php echo $base_controler; ?>',
        {val:val,'<?php echo $this->security->get_csrf_token_name(); ?>':hashValue}, 
        function(data)
        { 
            // Get return data to decode
            var obj = jQuery.parseJSON(data);
            // Get csrf new hash value
            var new_hash = obj.csrfHash;
            // Set csrf new hash value update
            jQuery('#csrf').val(new_hash);

        }
    );        

});

以下のようにコントローラーを設定してください

$reponse = array(
        'csrfName' => $this->security->get_csrf_token_name(),
        'csrfHash' => $this->security->get_csrf_hash()
        );
echo json_encode($reponse);

上記のすべてのコードは、リクエストごとにcsrfトークンを再作成します。

0
Md Suzon Mia