1

当我添加以下代码时,重新加载验证码工作正常

在 ZEND 表格中:

 $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,
    ));
4

1 回答 1

0

Zend_Form_Element_Hash 在每个请求上生成。因此,当您单击“刷新验证码图像”时,会生成一个新请求。然后,当您提交表单时,您已经用完了您的请求,因此 csrf 检查失败,因为令牌不同步。

要解决此问题,您可能会做错事,只需将跳数增加到某个较高的数字。不过,这将有助于否定您所追求的安全性。正确解决此问题的一种方法是在 refresh() 操作中重新初始化身份验证控制器中的令牌。然后,您可以发回包含此新令牌的 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);
于 2013-03-22T01:05:58.840 回答