Yii中的CSRF令牌超时?

时间:2015-04-01 01:35:54

标签: php yii csrf

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

我有一个单页应用程序,我的前端是用AngularJS编写的。在大多数情况下,我的CSRF令牌验证正常,我可以确认我通过每个请求发送令牌。但是,偶尔我会看到服务器上的错误说“无法验证CSRF令牌”。我不完全理解CSRF令牌如何被验证的内部结构,但有没有理由说明为什么会这样做?

我们的应用程序也是国际化的,但由于我们的服务器基础设施,某些地理区域的速度会减慢。我注意到(只是临时),例如,如果用户上传文件并且请求的时间比平时长,则CSRF令牌无效的可能性会更高。

很想听到有关此事的任何想法!提前谢谢!

1 个答案:

答案 0 :(得分:0)

我认为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
            ),

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