Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.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
Php 一个令牌与多个令牌以防止CSRF攻击_Php_Codeigniter_Security_Csrf - Fatal编程技术网

Php 一个令牌与多个令牌以防止CSRF攻击

Php 一个令牌与多个令牌以防止CSRF攻击,php,codeigniter,security,csrf,Php,Codeigniter,Security,Csrf,我正在使用Codeigniter,我想防止可能发生的CSRF攻击尝试。为了实现这一点,我向我想要保护的每个表单添加了一个带有随机标记的隐藏输入标记,同时我将该标记保存在会话中,以便在开始处理该表单数据时进行比较 // set a token to prevent CSRF attacks $csrf_token = md5(uniqid(rand(), true)); $this->session->set_userdata("csrf_token", $csrf_tok

我正在使用Codeigniter,我想防止可能发生的CSRF攻击尝试。为了实现这一点,我向我想要保护的每个表单添加了一个带有随机标记的隐藏输入标记,同时我将该标记保存在会话中,以便在开始处理该表单数据时进行比较

  // set a token to prevent CSRF attacks
  $csrf_token = md5(uniqid(rand(), true));
  $this->session->set_userdata("csrf_token", $csrf_token);
表格如下所示:

<form action="path/to/handler/page" method="post">
    <input type="text" name="title">
    <input type="text" name="date">
    <textarea name="content"></textarea>
    <input type="hidden" name="csrf_token" value="<?php echo $this->session->userdata("csrf_token") ?>"> 
    <input type="submit" name="submit" value="Save"> 
</form>
  // make sure there is no CSRF attack attempt
  $csrf_token = $this->session->userdata("csrf_token");
  if (empty($csrf_token) || $csrf_token !== $this->input->post("csrf_token")) {
    die("Some message here!!");
  }
这很有效。但正如您所看到的,我为每个包含表单的页面生成了一个随机标记,在某些情况下,如果我打开浏览器中的另一个选项卡以执行其他操作,就会导致问题。考虑这种情况:

  • 我打开
    add.php
    页面添加了一个新项目
  • 我填写了所有必需的数据,但我没有提交表格
  • 现在我决定在浏览器的另一个选项卡中打开
    edit.php
    页面来编辑现有项目
  • 然后我回到填写的
    add.php
    页面,并尝试提交数据

  • 此时,我将得到一个错误,因为当我打开
    add.php
    页面时,存储在会话中的令牌的值已被更改,并在我打开
    edit.php
    页面时被另一个令牌替换。那么我如何解决这个问题呢?当每个用户成功登录时,我是否应该为他生成一个令牌,然后在他可能处理的所有页面中使用该令牌?这种方法有任何风险或缺点吗?

    我浏览了你的帖子,没有发现不使用基本codeigniter CSRF保护的原因?看起来您正在重新发明轮子,并产生标准实现中不存在的问题

    更不用说你试图在每一张表单上打印你的代币,这违反了DRY原则。有什么不简单的理由吗

    Codeigniter具有内置的CSRF保护,可以在/application/config/config.php中启用

    $config['csrf_protection'] = TRUE;
    $config['csrf_token_name'] = 'csrf_token_name';
    $config['csrf_cookie_name'] = 'csrf_cookie_name';
    $config['csrf_expire'] = 7200;
    

    为了解决这个问题,您可以创建一个具有唯一密钥的令牌字符串,并将密钥/令牌对存储在会话中(作为CodeIgniter中的userdata)

    考虑到这种情况,您将需要以下步骤:

  • 创建唯一的令牌密钥
  • 正在创建令牌字符串
  • 在会话中存储密钥/令牌对(userdata)
  • 为CSRF密钥和令牌创建2个隐藏的
    元素
  • 通过检查会话中是否存在密钥/令牌来验证已发布的密钥/令牌
  • 开始工作:
    $csrf\u key=“令牌”。mt_rand(0,mt_getrandmax());
    $csrf_token=hash(“sha512”,mt_rand(0,mt_getrandmax());
    //在会话中存储密钥/令牌对
    $this->session->set_userdata($csrf_key,$csrf_token);
    
    添加隐藏的
    input
    s:

    
    
    不要使用
    rand()
    -出于安全目的,它不够随机。@SilverlightFox您建议使用什么替代方法?是否有任何理由在没有任何理由的情况下否决此答案?至少要说明原因。我看不出有什么理由重新发明轮子。谷歌搜索显示最糟糕的问题是IE8/9,codeigniter 2+解决了大部分问题。@DavidDuncan别担心,我对你的答案投了赞成票。