Zend CSRF 保护令牌在 Chrome 中不起作用 [英] Zend CSRF protection token doesn't work in Chrome

查看:17
本文介绍了Zend CSRF 保护令牌在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆