Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Codeigniter ajax CSRF问题_Javascript_Ajax_Codeigniter_Token - Fatal编程技术网

Javascript Codeigniter ajax CSRF问题

Javascript Codeigniter ajax CSRF问题,javascript,ajax,codeigniter,token,Javascript,Ajax,Codeigniter,Token,我做了一个简单的自动加载功能,当你在网站上向下滚动时加载内容。然而,当我在Codeigniter中启用CSRF保护时,似乎存在一些问题 我没有使用表单,所以我不知道在你滚动的时候,当我做我的post请求时,如何从a向B发送令牌 我的JavaScript if (location.href == baseurl) { $(window).scroll(function(){ if ($(window).scrollTop() > $('body').height()

我做了一个简单的自动加载功能,当你在网站上向下滚动时加载内容。然而,当我在Codeigniter中启用CSRF保护时,似乎存在一些问题

我没有使用表单,所以我不知道在你滚动的时候,当我做我的post请求时,如何从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请求上都需要一个令牌,所以当CSRF i启用时,我无法让它工作。有什么建议吗

启用CSRF时出错

加载资源失败:服务器响应状态为500(内部服务器错误)


如果我关闭CSRF,一切都很好…

如果您愿意,您可以在适当的地方回显令牌名称和哈希值。像这样的

 echo $this->security->get_csrf_token_name()


或者,您可以像往常一样使用form_open(),并使用javascript为您生成的隐藏输入。禁用CSRF功能是错误的做法。

基本上,您需要做的是从cookie中获取预期的CSRF值(默认情况下名为'ci_CSRF_token',然后将其与其他数据一起发布

您需要修改此行:

$.post(baseurl + 'ajax/images',{'id' : ID}, function(data) {
致:


可能需要安装cookie插件(我不太确定;我使用mootools)。这里有更多信息:。

您可能想试试我使用的这段代码。它非常有效:

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

$(函数(){
$('.answerlist')。每个(函数(e){
$(此)。单击(函数(){
var valrad=$(“输入[@name=answer]:选中”).val();
var post_数据={
“ansid”:瓦尔拉德,
'' : ''
};
$.ajax({
类型:“POST”,
url:“在线/检查答案”,
数据:post_数据,
成功:功能(msg){
///做点什么
}
});
});
});
});

正如其他人所说,您必须使用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>

前面的建议非常有效,但我发现使用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(); ?>';
    }); 
$(文档).ajaxSend(函数(elm、xhr、s){
如果(美国数据){
s、 数据+='&';
}
s、 数据+='=';
}); 

(适用于jquery-1.9.1。我不确定其他jquery版本)

以上几个答案的唯一问题是,csrf令牌仅对一个请求有效,因此如果您通过ajax发出post请求,并且不刷新页面,您将无法为下一个ajax post请求使用当前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调用。还要在每个post响应中包含此令牌,以便用于下一个post请求

然后在下一个ajax请求(javascript)中:


还请记住,我在哪里得到了
csrf_令牌:令牌
crf_令牌
替换为在application/config/config.php中找到的令牌的名称,该行声明
$config['csrf_令牌(name')='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和来自W3C的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(); ?>';
    }); 
$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)));
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 );
    }
});
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();
}