在提交Ajax时重新生成CRSF令牌codeigniter

时间:2016-12-30 15:36:48

标签: codeigniter

您好我正在寻找在使用ajax提交表单时在codeigniter中重新生成csrf令牌的过程。我希望在没有页面刷新的情况下重新生成令牌。有没有办法做到这一点。

5 个答案:

答案 0 :(得分:2)

根据具体情况,我在不同时间使用两种解决方案。

<强> 1。稍微凌乱的方式,但建议

获取控制器中的令牌名称和哈希值,并将其设置在页面上的某个位置作为数据字段(无论您选择哪个位置)。例如

 // get the data and pass it to your view
 $token_name = $this->security->get_csrf_token_name();
 $token_hash = $this->security->get_csrf_hash();

 // in your view file, load it into a div for instance
 <div id="my_div" data-token="<?php echo $token_name; ?>" data-hash="<?php echo $token_name; ?>"

现在在您的js ajax代码中,您只需读取“my_div”中的数据值即可获得适合您的ajax调用的数据。

如果你的页面上有一个真实的表单会更容易,在这种情况下,而不是使用一些div,只是不要在表单上使用form_open,而是自己创建隐藏的表单字段,这样你就可以阅读它很容易通过js。

 <input type="hidden" id="my_data" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />

这是重要的一点:当然在发送帖子数据后,您需要刷新令牌哈希值(在表单输入字段或div数据中,但是您选择这样做) 。编写一个名为'refresh_csrf_data'的js函数,并使用'GET'获取数据并更新字段。只要你完成了一个ajax帖子,就可以调用这个函数。

因此,每次ajax调用都会读取令牌数据,进行调用,然后刷新准备好下次调用的令牌数据。

<强> 2。简单但不太安全

或者,您可以使用

为ajax调用禁用CSRF
 $config['csrf_exclude_uris'] = array('controller/method');

在CSRF设置的配置文件中。

第3。更简单但也更不安全,我不使用它 最后,您可以在每次提交时关闭重新生成CSRF哈希

 $config['csrf_regenerate'] = FALSE;

但是,请谨慎行事。这可以让你接受某些类型的攻击。<​​/ p>

最适合您的答案完全取决于页面类型,用法,用户是否在此时登录,是关键任务还是次要内容,是财务等等。

没有什么是完全安全的,所以它有时是妥协。就个人而言,我会在完全重新生成时使用CSRF,在URI中没有例外,并在需要时重新加载令牌和哈希数据。它似乎很复杂,而且要解释一下,但是一旦你做了一次,在你需要的时候一次又一次地做起来真的很容易,你的网站将比仅仅避免其他选项的问题安全得多。 / p>

答案 1 :(得分:0)

  

我发现使用form helper函数可以更好地与Codeigniter一起使用   CSRF并停止抛出CSRF错误如果使用普通的html输入   将继续抛出CSRF错误。

这是一个AJAX示例

<?php echo form_open('controller/example', array('id' => 'form-login'));?>
<?php 

$username_array = array(
'name' => 'username',
'id' => 'username',
'class' => ''
);

echo form_input($username_array);

?>

<?php 

$password_array = array(
'name' => 'password',
'id' => 'password',
'class' => ''
);

echo form_password($password_array);

?>

<?php 

$submit_array = array(
'name' => 'submit',
'id' => 'submit',
'class' => '',
'value' => 'Submit',
'type' => 'submit'
);

echo form_input($submit_array);

?>

<?php echo form_close();?>

<script type="text/javascript">
$('#submit').click(function(e){

        e.preventDefault();

        var post_data = {
            'username' : $('#username').val(),
            'password' : $('#password').val(),
            '<?php echo $token_name; ?>' : '<?php echo $token_hash; ?>'
        };

        $.ajax
        ({ 
            type: 'post',
            url: "<?php echo base_url('example/');?>",
            data: post_data,
            dataType: 'json',
            success: function(response)
            {
                if (response['success'] == true) {

                    // Success

                } else {

                    // Error

                }

            }
        });
}); 
</script>

实施例

public function index() {
   $data['token_name'] = $this->security->get_csrf_token_name();
   $data['token_hash'] = $this->security->get_csrf_hash();

   $this->load->view('login_view', $data);
}

public function example() {
    $data = array('success' => false, 'messages' => array());

    $this->form_validation->set_rules('username', 'username', 'required');
    $this->form_validation->set_rules('password', 'password', 'required');

    if ($this->form_validation->run() == false) {

        foreach ($_POST as $key => $value) {
            $data['messages'][$key] = form_error($key);
        }

    } else {


        $data['success'] = true;
    }

    echo json_encode($data);
}

答案 2 :(得分:0)

如果它没有在会话中,那么你的控制器将是这样的

public function save_date() // or whatever function you like
{
 $regen_token = $this->security->get_csrf_hash();
 $data = array(
      "data" => $this->input->post('datas'),
 );
 $insert = $this->w_m->save($data);
 echo json_encode(array("regen_token" => $regen_token));
}
你的ajax中的

将如下所示:

$.ajax({
 url: "your url",
 type: "POST",
 data: { your data },
 dataType: "JSON",
 success: function(data)
 {
  $("name or id of your csrf").val(JSON.stringify(data.regen_token)).trigger("change"); // this will be the function that every post you'll request and it automatically change the value of your csrf without refreshing the page.
 },
 error: function(errorThrown)
 {
   console.log(errorThrown);
 }
});

答案 3 :(得分:0)

在回调中添加一个csrf哈希数组。

答案 4 :(得分:0)

对我有用的解决方案是,当为每个请求启用CSRF时,后续的ajax发布是在由于令牌过期而导致请求失败时,在AJAX成功中发出GET请求。然后有一个隐藏字段,该字段会继续用最新令牌更新,如果在发出请求时令牌已过期,则您进行GET REQUEST来获取最新令牌,然后在提交表单或提交POST请求的函数上触发click事件,这意味着该功能必须传递“ this”或ID作为参数的一部分。这使用户无法在后台实现续签令牌的过程