2013-10-27 107 views
3

我有csrf啓用codeigniter這是在FireFox和谷歌瀏覽器正常工作。然而,在IE它在web開發工具網絡面板顯示此錯誤:codeigniter csrf與Ajax不工作在IE

enter image description here

,並在詳細視圖:

enter image description here

$.post電話是:

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

ctn的值是保存CSRF標記值的cookie

ctn: 78346b5d0ec105efcce796f93ecc3cbb 

任何幫助或建議,調試更將不勝感激:當我做console.log('ctn: '+ctn)我得到正確顯示。

P.S .:我有一個vhost,我真的不知道它是否與IE有所不同。

更新:

我看了一下用CSRF在IE瀏覽器問題的一些建議使用P3P頭,所以我說這個標題索引頁:

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

但仍然有同樣的問題。

其他建議?

+0

你試過設置的contentType:'' 「應用/ JSON」''的要求?在旁註:我遇到了所有來自IE緩存Ajax請求的衆多問題... – moritzpflaum

+0

我已經試過了。不工作 –

+0

順便說一下,IE正在捕獲請求,但由於未驗證csrf,它將返回500。 –

回答

3

正如我在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

+0

所以你用雜貨的方式實施的方式。由於GC在IE中使用csrf來實現。 –

+0

在雜貨CRUD中,我使用Codeigniter的默認安裝簡單實現了csrf保護,並且它不適用於所有IE!然而,這不是雜貨CRUD的bug,這是Codeigniter的一個bug,所以我不能強迫用戶攻擊Codeigniter以使其工作。 這就是爲什麼我花時間寫了關於「在Codeigniter中不使用csrf_protection的5個原因」的文章。有些人喜歡這篇文章,但有些人討厭它。我知道答案不是你想要聽到的答案,但是這是我在用csrf保護掙扎幾天之後的看法:) –

+1

+ 1,約翰 - 我尊重你。因此,我尊重你的意見。 IE9 + IE10中的 它工作的很好,這就是爲什麼我問你,所以我可能有能力在我的代碼中應用相同的方式。無論如何,無論如何,感謝您的回答,我現在將繼續提出我的問題,以查看是否有其他人願意添加該問題。 –

2

由於@約翰與建議,由我自己來實現CSRF,我通過了第一期。然而,事實證明,IE瀏覽器根本沒有提交發布數據(調試後)所以,有一個問題在標題爲IE is refusing to send data through $.ajax 的計算器和解決這個問題,你必須添加這個meta標記告訴IE工作javascript在IE9兼容模式下。現在

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

,關於使用掛鉤,以解決CSRF的文章,它錯過一個問題是,如果你使用.serializeArray()或jQuery的任何等同於提交表單,您需要修改
validate_tokens函數檢查發佈數組內的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; 
    } 

} 

?>