2013-02-26 52 views
1

当我加入下面的代码重载的captcha做工精细当我在ZEND中添加CSRF时,为什么captcha重新加载不起作用?

在Zend中FORM:

$this->setName("login"); 
    $this->setMethod('post'); 

    $this->addElement('text', 'username', array(
    'filters' => array('StringTrim', 'StringToLower'), 
    'validators' => array(
     array('StringLength', false, array(0, 50)), 
    ), 
    'required' => true, 
    'label'  => 'Username:', 
    )); 

    $this->addElement('password', 'password', array(
    'filters' => array('StringTrim'), 
    'validators' => array(
     array('StringLength', false, array(0, 50)), 
    ), 
    'required' => true, 
    'label'  => 'Password:', 
    )); 


// Add a captcha 
$this->addElement('captcha', 'captcha', array(
'label'  => 'Please enter the 5 letters displayed below:', 
'required' => true, 
'captcha' => array(
    'captcha' => 'Figlet', 
    'wordLen' => 5, 
    'timeout' => 300 
) 
)); 



    $captcha = $this->createElement('captcha', 'captcha', array(
    'required' => true, 
    'captcha' => array(
     'captcha' => 'Image', 
     'font' => APPLICATION_PATH . '/../public/fonts/arial.ttf', 
     'fontSize' => '24', 
     'wordLen' => 5, 
     'height' => '50', 
     'width' => '150', 
     'imgDir' => APPLICATION_PATH.'/../public/captcha', 
     'imgUrl' => Zend_Controller_Front::getInstance()->getBaseUrl().'/captcha', 
     'dotNoiseLevel' => 50, 
     'lineNoiseLevel' => 5, 
    ), 
    'description' => 'Refresh Captcha Image' 

)); 

    $captcha->setLabel('Please type the words shown:'); 
    $captcha->removeDecorator("htmlTag")->removeDecorator('label'); 
    $captcha->addDecorator('Errors', array('class' => 'err-username', 'style' => 'display:none')); 
    $captcha->addDecorator('Description', array('id' => 'refreshcaptcha')); 

    $this->addElement($captcha); 
$this->getElement('captcha')->removeDecorator("htmlTag")->removeDecorator('label'); 

// And finally add some CSRF protection 
    /*$this->addElement('hash', 'csrf', array(
'ignore' => true, 
));*/ 

$this->addElement('submit', 'login', array(
'required' => false, 
'ignore' => true, 
'label' => 'Login', 
)); 

在PHTML:

<script type="text/javascript"> 
    $(document).ready(function() { 
     $('#refreshcaptcha').click(function() { 
      $.ajax({ 
       url: "<?php echo $this->url(array('controller' => 'auth', 'action' => 'refresh'), 'default', false) ?>", 
       dataType:'json', 
       success: function(data) { 
        $('#contactForm img').attr('src', data.src); 
        $('#captcha-id').attr('value', data.id); 
       } 
      }); 
     }); 
    }); 
    </script> 

    <?php 
     //Default 
     //$this->form->setAction($this->url()); 
     //echo $this->form; 
    ?> 

    <?php 
    $errorsMessages = $this->form->getMessages(); 
    //http://www.websitefactors.co.uk/zend-framework/2011/06/error-class-on-form-field-errors-using-zend-form/ 
    ?> 
    <?php 
    foreach($this->form->getMessages() as $elemName=>$messages) { 
     foreach($messages as $message) { 
      $label = $this->form->getElement($elemName)->getLabel(); 
      echo $this->escape($label.' '.$message)."<br>" ; 
     } 
    } 
    ?> 
    <div id="contactForm"> 
    <form method="<?php echo $this->form->getMethod(); ?>" action="<?php echo $this->form->getAction(); ?>"> 
    <?php echo $this->form->username->renderViewHelper(); ?> 
    <?php echo $this->form->password->renderViewHelper(); ?> 
    <?php echo $this->form->captcha; ?> 
    <?php //echo $this->form->csrf->renderViewHelper(); ?> 
    <?php echo $this->formSubmit('submit', 'Sign in',array('class'=>'button')); ?> 
    </form> 
    </div> 

当我点击 “刷新验证码图片” 时,验证码图像被替换而不刷新页面,并且它工作正常,但是当我添加下面的CSRF(跨站请求伪造)代码并重新加载验证码并提交时,登录永远不会成功。它给我的错误:“需要价值,不能为空”或“请键入词显示:验证码值是错误

$this->addElement('hash', 'csrf', array(
     'ignore' => true, 
    )); 

回答

0

Zend_Form_Element_Hash大干快上的每个请求生成。所以当你点击“Refresh Captcha Image”刷新一个新的请求时发生了什么。然后,当您提交表单时,您已经用完了您的请求,因此令牌检查失败,因为令牌不同步。

要解决这个问题,你可以做错误的事情,只是增加你的跳数到一些高数。尽管如此,这将有助于否定您之后的安全。正确解决此问题的一种方法是在refresh()操作中重新初始化auth控制器中的令牌。然后,您可以发送一个包含此新令牌的json_encoded响应。

.... 
$form->captcha->initCsrfToken(); //recreate token and send it back 
$responseArray['hash'] = $form->captcha->getValue(); 
echo Zend_Json::encode($responseArray); 

在你做了ajax调用之后,你就可以用你从refresh()动作中得到的东西替换这个标记。例如:

var newHash = jQuery.parseJSON(data).hash; 
$('#yourcsrfelement').val(newHash); 
+0

致命错误:在非对象 - $ form-> changealbumcsrf-> initCsrfToken()上调用成员函数initCsrfToken(); //重新创建令牌并将其发回原因? – Prashant 2013-06-12 10:52:37

+0

我的不好。我正在使用过去项目中的一些代码。复制/粘贴是:)我已经更新我的答案,使用您的验证码字段而不是我的。 – elightbo 2013-06-17 16:21:41

+0

我已经设置了这个代码,它的工作?在控制器中:$ form = new Application_Form_Loginother(); \t \t $ captcha = $ form-> getElement('captcha') - > getCaptcha(); \t \t //使用initCsrfToken GET HASH和RE-INITIALIZE \t \t $ csrf = $ form-> getElement('token'); \t \t $ csrf-> initCsrfToken(); \t \t \t \t $ data = array(); \t \t $ responseArray ['id'] = $ captcha-> ​​generate(); \t \t $ responseArray ['src'] = $ captcha-> ​​getImgUrl()。 $ captcha-> ​​getId()。 $ captcha-> ​​getSuffix(); \t \t $ responseArray ['hash'] = $ csrf-> getValue(); \t \t // echo Zend_Json :: encode($ responseArray); \t \t \t $ this - > _ helper-> json($ responseArray); – Prashant 2013-06-20 05:51:14

相关问题