2013-11-15 45 views
5

我正在使用CakePHP的SecurityComponent。这是非常重要的,因为它可以保存来自CSRF攻击的表单。我的项目总共有10-12个表单,这是我第一个CakePHP项目。在启用SecurityComponent后,我有点儿麻烦,但经过一些小心的分钟后可以消除。这是我的项目的最后一个形式,似乎一切都对我来说是正确的,但仍然是形式是黑洞:(任何人都可以告诉我的问题?我不想禁用CSRF检查或SecurityComponent。这是我的观点代码:请求已被黑洞 - CakePHP

<?php 
echo $this->Form->create('Record'); 
?> 
<script type="text/javascript"> var me = new MetroExam(); </script> 
<div class="exam_paper"> 
    <div class="question_box" id="q_b"> 
     <div class="q_n_a_header"> 
      <div class="instructions"> 
       <b>Instructions:</b><br> 
       <?=$inst['value_text']; ?> 
      </div> 
      <div id="timer">Please wait</div> 
     </div> 
     <div id="q_paper"> 
      <img id="q" style="display: none;" src="/oes/<?=$exam['path'].'?ts='.time(); ?>"> 

      <img id="loading_img" src="/oes/img/loading.gif"> 
     </div> 
    </div> 
    <div class="ans_box" id="a_b"> 
     <!-- information about answer paper. !important --> 
     <?php 
     $i = 0; 

     //these fields are essential for evaluating ans paper 
     echo $this->Form->hidden('submit', array('value' => 'true')); 
     echo $this->Form->hidden('start_time', array('value' => '')); 
     echo $this->Form->hidden('end_time', array('value' => '')); 
     echo $this->Form->hidden('duration', array('value' => '')); 
     echo $this->Form->hidden('valid', array('value' => '')); 
     echo $this->Form->hidden('passed', array('value' => '')); 

     //options for all radio 
     $options  = array(
      '1' => 'A', 
      '2' => 'B', 
      '3' => 'C', 
      '4' => 'D' 
     ); 
     if($exam['choices'] == 5){ 
      $options['5'] = 'None'; 
     } 

     $questions = (int)$exam['questions']; // 40 <= $exam['questions'] <= 100 
     $i = 1; 
     while($questions--){ 
      echo '<div class="'.(($i%2)==1?'each_answer_even':'each_answer_odd').'" id="ans-'.$i.'">'; 
      echo '<div class="q_number">'.($i <= 9 ? '0'.$i : $i).'</div>'; 
      $name  = 'ans'.str_pad($i, 3, '0', STR_PAD_LEFT); 
      $attributes = array('empty' => false, 'legend' => false, 'onclick' => 'me.answer_click('.$i.')'); 
      echo '<div class="mcq">'.$this->Form->radio($name, $options, $attributes).'</div>'; 
      echo '</div>'; 
      $i++; 
     } 
     echo $this->Form->end('Submit'); 
     ?> 
    </div> 
</div> 

这基本上是一个MCQ考试形式,其中每个组具有在形式4个或5单选按钮和总共40个到100个组我使用CakePHP 2.4预先感谢

+0

你有没有机会用javascript改变隐藏输入的值? – Nunser

+0

是的,我愿意。我正在通过jQuery改变4/5隐藏字段。但这是问题吗? –

+1

也许吧,但让我们来调试吧。尝试更改隐藏的简单文本输入并尝试提交表单。如果提交,那么这是你的问题,我会回答解释和可能的解决方案。如果不是,那么我们必须看看还能有什么。 – Nunser

回答

9
。。

根据注释,问题的出现是因为你正在改变表单的隐藏值SecurityComponent的工作方式是它“锁定”字段的名称,所以恶意者不能添加新字段或更改值一旦表格被发送,但是它对隐藏值更加严格,因为它锁定了字段名称的值。所以通过使用jQuery来改变它,你就会破坏你自己的形式。

有一个很好的小贴子,我学到了这个,拿look at it。作者还解释了绕过这个问题的两种方法。一种是禁用隐藏字段的安全性,所以为令牌计算的哈希不包括那些值...这是不是真的安全...
而另一种解决方案是修改FormHelper,并告诉它“锁定”隐藏字段名称但不是值。我不记得作者使用什么版本的Cake,但在那里给出的代码应该是实用的。因此,通过该解决方案,您可以通过选项数组来告诉表单对您不那么严格。

哦,还有其他的选择(这是我通常使用的)(我现在只是读了它......我想我自己想到了......哦),只是使用普通输入你想隐藏的文本字段,并添加一个像display:none这样的css风格。

这取决于你自己认为最好的。我喜欢css选项,因为它更简单,而且真的,如果有人打算用我的css(比如萤火虫或类似的东西)来混淆,他们可能会用隐藏字段的值来做它,它不需要任何更多的努力。无论如何,您应该在处理表单提交时采取所有额外的步骤和验证。但就像我说的,对你而言,你认为最适合你的情况。

1

除了已发布的内容之外,还有一些可能导致问题的内容:对我而言,隐藏的输入会覆盖名称。

$this->Form->create('ExampleModel'): 
$this->Form->input('foo_bar', array(
    'type' => 'hidden', 
    'name' => 'foo_bar', 
)); 

其结果是,最终$this->request->data有对应的键$this->request->data['foo_bar']。它不在$this->request->data['ExampleModel']阵列内,这就是问题所在。

要解决该问题,我必须从模板中删除name键,使输入属于模型的数据,然后将控制器更改为接受该值。

希望这可以帮助别人。

更新:这也适用于不附加到任何模型的表单,例如,:

$this->Form->create(false, array(
    'url' => '/example', 
)):