Yii中的CSRF令牌超时


CSRF token in Yii timing out?

我的CSRF令牌似乎超时了。有什么办法可以防止这种情况发生吗?

我有一个单页应用程序,我的前端是用AngularJS编写的。在大多数情况下,我的CSRF令牌验证良好,我可以确认我通过每个请求都发送了令牌。然而,偶尔我会看到来自服务器的错误,说"CSRF令牌无法验证"。我不完全理解CSRF令牌是如何验证的,但有什么原因会发生这种情况吗?

我们的应用程序也是国际化的,但由于我们的服务器基础设施,某些地理区域的速度有所放缓。我注意到(只是临时的),例如,如果用户正在上传一个文件,并且请求的时间比平时长,那么CSRF令牌无效的几率就会更高。

很想听听关于这个的任何想法!提前感谢!

我认为Yii正在根据cookie验证CSRF,请尝试扩展CHttpRequest基类并根据会话进行验证。这导致会话超时与CSRF有效性的差异。

class HttpRequest extends CHttpRequest
{
    public function getCsrfToken()
        {
            if ($this->_csrfToken === null) {
                $session = Yii::app()->session;
                $csrfToken = $session->itemAt($this->csrfTokenName);
                if ($csrfToken === null) {
                    $csrfToken = sha1(uniqid(mt_rand(), true));
                    $session->add($this->csrfTokenName, $csrfToken);
                }
                $this->_csrfToken = $csrfToken;
            }
            return $this->_csrfToken;
        }
        public function validateCsrfToken($event)
        {
            if ($this->getIsPostRequest()) {
                // only validate POST requests
                $session = Yii::app()->session;
                $headers = Common::getAllHeaders();
                if ($session->contains($this->csrfTokenName) && (isset($_POST[$this->csrfTokenName]) || isset($headers['X-Csrf-Token']))) {
                    $tokenFromSession = $session->itemAt($this->csrfTokenName);
                    $tokenFromPost = isset($_POST[$this->csrfTokenName]) ? $_POST[$this->csrfTokenName] : $headers['X-Csrf-Token'];
                    $valid = $tokenFromSession === $tokenFromPost;
                } else {
                    $valid = false;
                }
                if (!$valid) {
                    header("Location: " . Yii::app()->createAbsoluteUrl(Yii::app()->request->url));
                }
            }
        }
}

并在您的配置文件中使用它:

'request' => array(
            'enableCsrfValidation' => true,
            'class' => 'HttpRequest',
            'csrfCookie' => array(
                'httpOnly' => true,
                'secure' => true
            ),

注意:不要复制粘贴所有内容。根据您的需要进行修改。这只是一个开始。希望我能理解你的问题。