Codeigniter CSRF valid for only one time ajax request

前端 未结 9 838
鱼传尺愫
鱼传尺愫 2020-12-03 11:46

I want to upload image on the server on change event of jQuery but using codeigniter csrf I am able to upload image only one time. How can I upload images using ajax for mul

相关标签:
9条回答
  • 2020-12-03 11:46

    Each time you make a request, the csrf_token is being updated by CI. That's why the CSRF only work once. So everytime we make a request we need to update the csrf_token too. I solve this problem by doing this.

    Conroller: get the updated csrf using this code.

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

    AJAX: replace the old value of 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);
            });
    

    Important!: use dataType: 'json'

    So now each time you have a successful request, the csrf_token is updated too and you are now free from 403 (Forbidden) error.

    0 讨论(0)
  • 2020-12-03 11:52

    You can set this in config.php

    $config['csrf_regenerate'] = FALSE;
    

    so the csrf protection is valid during all the session time it will solve your problem. If you set $config['csrf_regenerate'] = true; then CI generate new csrf token every request so your old csrf token not match with new generated csrf token

    0 讨论(0)
  • 2020-12-03 11:53

    Please try like my code. its working my application

    your view file

    $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; ?>" />
    

    after set jquery post method like below

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

    please set your controller like below

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

    above all code recreate your csrf token each request.

    0 讨论(0)
  • 2020-12-03 11:57

    $config['csrf_regenerate'] = TRUE;

    keep auto generate to true it will be more safer. In similar case when csrf is expired in first request. What i have implemented

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

    In every ajax response we are passing csrf data in which latest csrf data will be replaced with current one

    Sample response from request

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

    I update csrf token in every ajax request. Also don't choose this method if you are working with multi tab environment

    0 讨论(0)
  • 2020-12-03 12:01

    All you need to do is reload the CSRF token in your AJAX response. It is that simple!.

    0 讨论(0)
  • 2020-12-03 12:02

    Maybe you can try using jquery cookie

    First you need to add this

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.js"></script>
    

    then change your code to this

    $("#avatar").change(function(){
    var link = $("#avatar").val();     
    $.ajax({
        url : "<?php echo base_url('main/test'); ?>",
        type: 'post',
        data: {csrf_test_name: $.cookie('csrf_cookie_name'),"id":"hello","link":link},
        dataType : "JSON",
        success : function(data)
        {   
            alert(data);
        }  
    });
    

    Finally you can try to set your csrf_protection to true

    [csrf_protection] = TRUE;
    
    0 讨论(0)
提交回复
热议问题