【问题标题】:codeigniter csrf with ajax not working in IE带有ajax的codeigniter csrf在IE中不起作用
【发布时间】:2023-03-05 09:23:02
【问题描述】:

我使用 codeigniter 启用了 csrf,它在 FireFox 和 Google Chrome 中正常工作。但是在 IE 中,它在 Web 开发人员工具网络面板中显示此错误:

详细视图:

我的$.post 电话是:

var ctn = $.cookie('csrf_cookie');
$.post('some_path', {
    'my_token': ctn
}, function (data) {
    if (data.res == 'something') {
        //process here
    }, 'json');

当我执行console.log('ctn: '+ctn) 时,ctn 的值(即保存 CSRF 令牌值的 cookie)正确显示:

ctn: 78346b5d0ec105efcce796f93ecc3cbb 

任何帮助或调试更多的建议将不胜感激。

P.S.:我有一个vhost,我真的不知道它是否对 IE 有影响。

更新:

我已经阅读了关于 IE 中 CSRF 的问题,一些建议使用 P3P 标头,所以我将此标头添加到索引页面:

header('P3P:CP="IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT');

但还是有同样的问题。

还有其他建议吗?

【问题讨论】:

  • 您是否尝试为请求设置 contentType: "application/json" ?附带说明:我遇到了许多问题,这些问题都来自 IE 缓存 ajax 请求......
  • 我已经试过了。不工作
  • 顺便说一句,IE 正在捕获请求,但由于 csrf 未经过验证而返回 500。
  • 我在 csrf 上遇到了同样的问题,所以我直接在 php 文件中使用 js 并在 ajax 中传递数据,例如 data:{ 'security->get_csrf_token_name(); ?>':'security->get_csrf_hash(); ?>', 'start':convert(start), 'end':convert(end), 'allDay':allDay, 'title':'title' },它对我来说很好

标签: jquery ajax codeigniter internet-explorer csrf


【解决方案1】:

正如我在my article 中建议的那样。最好使用 net.tutsplus 中的帖子,标题为:Protect a CodeIgniter Application Against CSRF。这是一篇旧帖子,解决方案适用于 Codeignter 1.7.x 。然而,这是迄今为止我能找到的唯一适合 Codeigniter 2 的解决方案,以便在 Codeigniter 中实现 CSRF 保护。我们在这里遇到的主要问题是 Codeigniter 使用了 COOKIE。然而,这篇文章使用了 Codeigniter 会话,它使用起来更安全,并且适用于所有浏览器,没有任何问题。 net.tutsplus 的文章适用于 AJAX 和非 AJAX 请求。

所以我的建议是,如果你没有找到解决问题的方法,你可以尝试实现这篇文章:Protect a CodeIgniter Application Against CSRF

【讨论】:

  • 那么您使用杂货杂货的实施方式。由于 GC 在 IE 中工作并实现了 csrf。
  • +1,约翰-我尊重你。因此,我尊重你的意见。在 IE9 + IE10 中它工作得很好,这就是我问你的原因,所以我可能有能力在我的代码中应用相同的方式。无论如何,感谢您的回答,我现在将保留我的问题,看看是否还有其他人愿意添加它。
  • 嗨,我确实实现了它,并且我发布了一个答案来解释确切的问题。谢谢你的帮助。 :D
  • 您好 @mamdouhalramadan ,我很高兴能帮助您解决这个问题。此外,我更高兴的是,对于如此常见的问题“codeigniter csrf with ajax not working in IE?”终于有了一个正确的答案。我认为您的回答也会对其他人有所帮助。
  • 是的,当然,杂货店 CRUD 的所有社交媒体都在以下页脚的右侧:grocerycrud.com ;-) 有 fb、g+、twitter 和 github :)
【解决方案2】:

感谢 @John 提出我自己实现 CSRF 的建议,我通过了第一个问题。然而,事实证明IE根本没有提交post数据(调试后)所以,stackoverflow上有一个标题为IE is refusing to send data through $.ajax的问题 为了解决这个问题,你必须添加这个meta标签来告诉IE在IE9兼容模式下使用javascript。

<meta http-equiv="x-ua-compatible" content="IE=9" >

现在,关于使用钩子解决 csrf 的文章,它遗漏了一个问题,即如果您使用 .serializeArray() 或 jquery 中的任何等效项来提交您的表单,您需要修改
@987654325 @ 函数检查已发布数组中的token_name

希望这能拯救遇到同样问题的人

注意:添加meta标签而不重写csrf不会解决问题。

更新 1:

这是我正在使用的实现:

<?php
/**
 * Description of csrf_protection
 * @author Ian Murray
 */
class Csrf_Protection {

    private $CI;
    private static $token_name = 'somename';
    private static $token;

    public function __construct() {
        $this->CI = &get_instance();
    }

/** 
 * Generates a CSRF token and stores it on session. Only one token per session is generated. 
 * This must be tied to a post-controller hook, and before the hook 
 * that calls the inject_tokens method(). 
 * 
 * @return void 
 * @author Ian Murray 
 */ 
    public function generate_token()  
    {  
          // Load session library if not loaded  
          $this->CI->load->library('session');  

          if ($this->CI->session->userdata(self::$token_name) === FALSE)  
          {  
            // Generate a token and store it on session, since old one appears to have expired.  
            self::$token = md5(uniqid() . microtime() . rand());

            $this->CI->session->set_userdata(self::$token_name, self::$token);  
          }  
          else  
          {  
            // Set it to local variable for easy access  
            self::$token = $this->CI->session->userdata(self::$token_name);  
          }  
    }  

    /** 
    * Validates a submitted token when POST request is made. 
    * 
    * @return void 
    * @author Ian Murray 
    */  
   public function validate_tokens()  
   {  
     // Is this a post request?  
     if ($_SERVER['REQUEST_METHOD'] == 'POST')  
     {  
       // Is the token field set and valid?  
       $posted_token = $this->CI->input->post(self::$token_name);  
       if($posted_token === FALSE){
           $posted_token = $this->_get_token_in_post_array($this->CI->input->post());
           $this->_check_all_post_array($posted_token);
       }
     }  
   }
   /**
   *takes the posted token and check it after multidimesional-array search
   *@params $posted_token
   *@author Mamdouh Alramadan
   */
   private function _check_all_post_array($posted_token)
   {
       if ($posted_token === 'error' || $posted_token != $this->CI->session->userdata(self::$token_name))  
       {  
         // Invalid request, send error 400.
         show_error('Request was invalid. Tokens did not match.', 400);  
       }  
   }


   /** 
    * This injects hidden tags on all POST forms with the csrf token. 
    * Also injects meta headers in <head> of output (if exists) for easy access 
    * from JS frameworks. 
    * 
    * @return void 
    * @author Ian Murray 
    */  
   public function inject_tokens()  
   {  
     $output = $this->CI->output->get_output();  

     // Inject into form  
     $output = preg_replace('/(<(form|FORM)[^>]*(method|METHOD)="(post|POST)"[^>]*>)/',  
                            '$0<input type="hidden" name="' . self::$token_name . '" value="' . self::$token . '">',   
                            $output);  

     // Inject into <head>  
     $output = preg_replace('/(<\/head>)/',  
                            '<meta name="cname" content="' . self::$token_name . '">' . "\n" . '<meta name="cval" content="' . self::$token . '">' . "\n" . '$0',   
                            $output);  

     $this->CI->output->_display($output);  
   }  


/**
 * takes the posted array and check for the token inside it 
 * @params $arr array
 * @author Mamdouh Alramadan
 */
   private function _get_token_in_post_array($arr)
   {//this function is customized to my case but it's easy to adapt
       if(is_array($arr)){
        $key = $this->_recursive_post_array_search(self::$token_name, $arr);//this will return data if token found
        if($key === 'data'){//I'm expecting the token inside data array
            $key = $this->_recursive_post_array_search(self::$token_name, $arr['data']);
            return isset($arr['data'][$key]['value'])?$arr['data'][$key]['value']:FALSE;
        }
       }
       return 'error';
   }
   //some custom function to do multi-dimensional array search, can be replaced with any other searching function.
   private function _recursive_post_array_search($needle,$haystack) {
        foreach($haystack as $key=>$value) {
            $current_key=$key;
            if($needle===$value OR (is_array($value) && $this->_recursive_post_array_search($needle,$value) !== false)) {
                return $current_key;
            }
        }
        return false;
    }

}

?>

【讨论】:

    猜你喜欢
    • 2014-06-21
    • 1970-01-01
    • 1970-01-01
    • 2012-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多