【问题标题】:Regenerate CRSF token codeigniter on submit Ajax在提交 Ajax 时生成 CSRF 令牌代码点火器
【发布时间】:2016-12-30 15:36:47
【问题描述】:

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

【问题讨论】:

    标签: codeigniter


    【解决方案1】:

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

    【讨论】:

      【解决方案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;
      

      但是,请谨慎行事。这可能会使您面临某些类型的攻击。

      最适合您的答案完全取决于页面的类型、使用情况、用户当时是否登录、是关键任务还是次要问题、财务等。

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

      【讨论】:

        【解决方案3】:

        我发现使用 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);
        }
        

        【讨论】:

        • 这对于一次性的 js 来说是件好事,但对于 ajax 就不行了。下次调用该函数时,令牌将无效。如果 js 在 .js 文件中而不是在控制器或视图中编码,也不起作用。
        • 我有 4 个 Ajax 调用,其中一个在前一个调用之后执行,例如 Car's Make,Model,Sub-Model,Year。问题是只有第一个 Ajax 调用有效。其他人给出错误 403。对此有什么解决方案?
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 2015-12-05
            • 2012-04-10
            • 2016-01-13
            • 2010-12-20
            • 1970-01-01
            • 2018-07-29
            • 1970-01-01
            • 2014-01-21
            • 2016-12-08
            相关资源
            最近更新 更多