2012-01-05 151 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