当我添加以下代码时,重新加载验证码工作正常
以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,
));
答案 0 :(得分:0)
每次请求都会生成Zend_Form_Element_Hash。所以当你点击“刷新验证图像”时会发生新的请求。然后,当您提交表单时,您已经用完了请求,因此csrf检查失败,因为令牌不同步。
要解决此问题,您可能会做错事,只是将跳数增加到一些高数字。但这有助于否定你所追求的安全性。正确解决此问题的一种方法是在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);