Zend CSRF 保护令牌在 Chrome 中不起作用 [英] Zend CSRF protection token doesn't work in Chrome
问题描述
所以这是我用来创建表单对象的方法:
So here is a method I'm using to create form objects:
protected function _getForm($form, $action = null)
{
require_once(APPLICATION_PATH.'/modules/'.$this->_request->getModuleName().'/forms/'.$form.'.php');
$form = new $form();
if (null !== $action) {
$form->setAction($action);
}
$csrfNamespace = new Zend_Session_Namespace('Tokens');
if (false === isset($csrfNamespace->csrfToken)) {
$csrfNamespace->csrfToken = $this->_helper->randomString();
}
$csrfToken = new Zend_Form_Element_Hidden('csrf_token');
$csrfToken->setValue($csrfNamespace->csrfToken)
->addValidator(new My_Validator_CSRF())
->removeDecorator('HtmlTag')
->removeDecorator('Label');
$form->addElement($csrfToken);
return $form;
}
如您所见,我正在创建一个随机字符串令牌并向表单添加一个 My_Validator_CSRF() 验证器.这是验证器:
As you can see, I am creating a random string token and adding a My_Validator_CSRF() validator to the form. Here is the validator:
<?php
class My_Validator_CSRF extends Zend_Validate_Abstract
{
const TOKEN_NOT_SET = 'notSet';
const TOKEN_INVALID = 'invalid';
protected $_messageTemplates = array(
self::TOKEN_NOT_SET => "'%value%' cannot be compared to anything, token has not been generated",
self::TOKEN_INVALID => "'%value%' is not valid token"
);
public function isValid($value)
{
$this->_setValue($value);
$isValid = true;
$csrfNamespace = new Zend_Session_Namespace('Tokens');
if (false === isset($csrfNamespace->csrfToken)) {
$this->_error(self::TOKEN_NOT_SET);
$isValid = false;
}
if ($csrfNamespace->csrfToken !== $value) {
$this->_error(self::TOKEN_INVALID);
$isValid = false;
}
return $isValid;
}
}
这在 Firefox 和 IE 中效果很好,但在 Chrome 中我不断收到错误消息:
This works great in Firefox and IE but in Chrome I keep getting the error message:
"b6be61a6aece979d15eb1f605e109f32" is not valid token
每次页面刷新后令牌都会更改.它在 Firefox 和 IE 中没有.难道我做错了什么?这是我开始会话的方式:
And the token changes after each page refresh. Which it does not in Firefox and IE. Am I doing something wrong? Here is how I start the session:
ini_set('session.cookie_secure', 1);
ini_set('session.cookie_httponly', 1);
ini_set('session.use_only_cookies', 1);
// start the session
Zend_Session::start();
推荐答案
这个问题也出现在 Zend_Form_Element_Hash - ZF-10714 似乎是同样的问题 - 一切都适用于 Firefox 和 IE,但不适用于 Chrome,我不断收到两个给定的令牌不匹配";验证失败.
This issue appears also for Zend_Form_Element_Hash - ZF-10714 seems to be the same issue - everything works with Firefox and IE but not in Chrome where I keep getting the "The two given tokens do not match" validation failure.
当剥离我的应用程序进行调试时,我设法将错误定位到重定向.当 Chrome 尝试在后台缓存下一页时,它会在同一会话中触发一个新的 CSRF,覆盖旧的 CSRF 令牌.主要的罪魁祸首是我的控制器插件处理 Zend_Auth/Acl 部分,如果浏览器会话(用户)未登录并让 Chrome 为登录触发新的 CSRF,我将重定向到登录页面无法在 Chrome 上登录.
When stripping down my application for debugging I managed to locate the error to redirects. When Chrome tries behind the scenes cache the next page it triggers a new CSRF in the same session overwriting the old CSRF token. The major culprit was in my case my controller pluging dealing with the Zend_Auth/Acl part where I redirected to the login page if the browser session (the user) wasn't logged in and got Chrome to trigger a new CSRF for the login - making it impossible to login on Chrome.
如果用户缺乏特定操作的权限,他/她会被要求通过 ErrorController loginAction() 或 permissionAction() 中的单独链接进入登录页面
If a user lacks permissions for a certain action he/she is asked to go to the login page through a separate link in the ErrorController loginAction() or permissionAction()
我使用自定义 Zend_Dojo_Form 类扩展表单:
I extend the forms with a custome Zend_Dojo_Form class:
abstract class Form_Base extends Zend_Dojo_Form {
public function __construct($options = null) {
parent::__construct($options);
$token_id = "csrf_token_id_" . strtolower(get_called_class());
$this->addElement('hash', $token_id);
}
}
我希望这会有所帮助,这个问题至少让我非常恼火,我很高兴我终于似乎控制了问题.您还可以查看 ZF 错误,我在其中发布了大部分内容我的调试控制器.
I hope this helps, this problem annoyed at least me immensely and I'm glad that I finally seem to have the problem under control. You can also check out the ZF bug where I've posted most parts of my debug controller.
这篇关于Zend CSRF 保护令牌在 Chrome 中不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!