2012-01-05 157 views
1

我在後端使用codeigniter。Codeigniter AJAX CSRF保護

最近我聽說「CSRF」一詞,並決定保護請求。

幾乎我的網站上所有的動作是通過Ajax &有時我創建使用DOM操作/追加網頁內容[這裏的疑問,我怎麼能注入CSRF令牌的視圖文件?]

Okkey,之後,我該如何驗證?

假設我將這些值添加爲令牌並傳遞給服務器,那麼我可以使用構造函數來檢查&驗證此?

例:

Class Cl_Controller extends Ci_controller 
{ 
    function __construct() 
{ 
    //loading libraries,models,helpers etc... 

    if (isset($this->input->get_post("CSRF_TOKEN")) || _another_condition_) 
    { 
     // The CSRF TOKEN is invalid or null ,the action cannot be done... 
    } 
} 
function register() 
{ 
    //some codes... 
} 
function delete_user() 
{ 
    //some codes 
} 
} 

是否有可能做一些事情聯繫呢?

請給我一些好主意&平時的做法。

謝謝。

+0

[CSRF預防](http://en.wikipedia.org/wiki/Cross-site_request_forgery#Prevention) – hakre 2012-01-05 09:29:39

+0

[笨CSRF保護使用Ajax(http://ericlbarnes.com/post/10728867961/ codeigniter-csrf-protection-with-ajax)可能會有所幫助。 – Mudshark 2012-01-05 11:34:01

回答

3

對於我的ajax調用,我通常會執行兩次檢查;

確保它是一個ajax請求,使用一個小幫助文件。

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

if (! function_exists('ajax_check')) { 
    /** 
    * Check AJAX 
    * 
    * Checks to see if you (or the royal I) are dealing with an AJAX call. 
    * 
    * @return boolean 
    */ 
    function ajax_check() { 
     if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') { 
      return TRUE; 
     } else { 
      show_404(); 
      return FALSE; 
     } 
    } 
} 

if (! function_exists('ajax_response')) { 
    /** 
    * JSON Response Wrapper 
    * 
    * Wraps up any data nicely for sending back to an ajax call 
    * 
    * @return string 
    */ 
    function ajax_response($status, $data) { 
     if (!is_array($data)) { 
      $data = array(); 
     } 
     // Set the JSON header appropriately 
     header('Content-Type: application/json'); 
     // Echo out the array into json 
     echo json_encode(array_merge(array('status' => $status), $data)); 
     exit; 
    } 
} 

if (! function_exists('ajax_force_fail')) { 
    /** 
    * Force AJAX Failure 
    * 
    * If you ever need to, force an AJAX to fail 
    */ 
    function ajax_force_fail() { 
     $_ci =& get_instance(); 
     $_ci->output->set_status_header(500); 
    } 
} 

用法like;

public function some_function() { 
    $this->load->helper('ajax'); 
    ajax_check(); 

    try { 
     // do something 
     ajax_response('success', array('data' => $some_var)); 
    } catch (Exception $e) { 
     ajax_response('failure', array('data' => $e->getMessage())); 
    } 
} 

和xsrf的類似方法。 文件:

<?php if (! defined('BASEPATH')) exit('No direct script access allowed'); 

if (! function_exists('xsrf_get_token')) { 
    /** 
    * Get XSRF Token 
    * 
    * Returns a token that exists for one request that verifies that 
    * the action was executed by the person that requested it 
    * 
    * @return string 
    */ 
    function xsrf_get_token() { 
     $ci =& get_instance(); 
     if ($ci->session->userdata('xsrf_hash')) { 
      $token = $ci->session->userdata('xsrf_hash'); 
     } else { 
      // Generate the token 
      $token = sha1(microtime().$ci->uri->uri_string()); 
      // Set it in the session 
      $ci->session->set_userdata('xsrf_hash', $token); 
     } 

     //Return it 
     return $token; 
    } 
} 

if (! function_exists('xsrf_get_token_field')) { 
    /** 
    * Get XSRF Token Field 
    * 
    * Returns an xhtml form element to include xsrf token. 
    * You can specify the id/name attribute of the input. 
    * Has a dependancy to get_xsrf_token(). 
    * 
    * @param string The id/name to be used 
    * @return string 
    */ 
    function xsrf_get_token_field($name='auth_token') { 
     return '<input type="hidden" id="'.$name.'" name="'.$name.'" value="' .xsrf_get_token(). '" />'; 
    } 
} 

if (! function_exists('xsrf_delete_token')) { 
    /** 
    * Delete XSRF Token 
    * 
    * Deletes the xsrf token 
    * 
    * @return boolean 
    */ 
    function xsrf_delete_token() { 
     $ci =& get_instance(); 
     if ($ci->session->userdata('xsrf_hash')) { 
      $ci->session->unset_userdata('xsrf_hash'); 
      return TRUE; 
     } else { 
      return FALSE; 
     } 
    } 
} 

if (! function_exists('xsrf_check_token')) { 
    /** 
    * Get XSRF Token Field 
    * 
    * Checks that the token is still valid, returns true if so. 
    * Deletes old token after valid or fail. 
    * Has a dependacy to xsrf_delete_token() 
    * 
    * @param string The challenge token 
    * @return boolean 
    */ 
    function xsrf_check_token($challenge_token) { 
     // CI 
     $ci =& get_instance(); 
     // Get the stored token 
     $token = $ci->session->userdata('xsrf_hash'); 
     // Delete the old token 
     xsrf_delete_token(); 
     // Returns if the token is the right token 
     return ($token == $challenge_token); 
    } 
} 

用法(控制器);

public function some_other_function() { 
    $this->form_validation->set_rules('username', 'Username', 'required|callback_check_token'); 
    if($this->form_validation->run() == TRUE) { 
     // do something 
    } else { 
     // something else 
    } 
} 

// callback function 
public function check_token($val) { 
    if (xsrf_check_token($val) == TRUE) { 
     return TRUE; 
    } else { 
     $this->form_validation->set_message('check_token', 'Oops'); 
     return FALSE; 
    } 
} 

鑑於;

<form action="" method="post"> 
    <?php echo xsrf_get_token_field(); ?> 
    ... 
</form> 
+0

在視圖中,您必須回顯xsrf_get_token_field(),因爲它返回的是html,不會直接回顯它。 – manavo 2012-01-05 13:03:39

+0

我的不好,已經改變了答案。 – Rooneyl 2012-01-06 08:16:03

+0

這是好的,但我不能直接在我的視圖文件上使用php代碼,因爲它由java腳本[某些部分]生成。 – Red 2012-01-06 11:52:42