Yii2 CSRF

概述:Yii2 默认全局开启csrf验证的
1.配置csrf隐藏表单的input name

'components' => [
        'request' => [
            'csrfParam' => '_csrf-frontend',
        ],
]

2.表单嵌入csrf


3.yii2 csrf验证机制
yii\web\Controller

/**
     * {@inheritdoc}
     */
    public function beforeAction($action)
    {
        if (parent::beforeAction($action)) {
            //调用csrf_token 验证方法
            if ($this->enableCsrfValidation && Yii::$app->getErrorHandler()->exception === null && !Yii::$app->getRequest()->validateCsrfToken()) {
                throw new BadRequestHttpException(Yii::t('yii', 'Unable to verify your data submission.'));
            }

            return true;
        }

        return false;
    }

yii\web\Request

public function validateCsrfToken($clientSuppliedToken = null)
    {
        $method = $this->getMethod();
        // only validate CSRF token on non-"safe" methods https://tools.ietf.org/html/rfc2616#section-9.1.1
        if (!$this->enableCsrfValidation || in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {
            return true;
        }
       //获取服务器的csrftoken
        $trueToken = $this->getCsrfToken();

        if ($clientSuppliedToken !== null) {
            return $this->validateCsrfTokenInternal($clientSuppliedToken, $trueToken);
        }
        //验证客户端传过来的csrf_token
        return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken)
            || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken);
    }

4.客户端如何传递csrf_token
form表单POST提交


AJAX提交 yii已做了自动处理
yii.js

function initCsrfHandler() {
        // automatically send CSRF token for all AJAX requests
        $.ajaxPrefilter(function (options, originalOptions, xhr) {
            if (!options.crossDomain && pub.getCsrfParam()) {
                xhr.setRequestHeader('X-CSRF-Token', pub.getCsrfToken());
            }
        });
        pub.refreshCsrfToken();
    }

5.为什么每次刷新界面csrf_token都会刷新变化,而不影响验证呢?
csrf_token 是存在会话的cookie中的,而每次都变化是Yii2做了处理,尽管输出到界面的值不断变化,但存在cookie里面的真正值是不变的。

public function getCsrfToken($regenerate = false)
    {
        if ($this->_csrfToken === null || $regenerate) {

            $token = $this->loadCsrfToken();
            if ($regenerate || empty($token)) {
                $token = $this->generateCsrfToken();
            }
            $this->_csrfToken = Yii::$app->security->maskToken($token); //这里经过处理csrf_token每次变化,但是$token始终唯一
        }

        return $this->_csrfToken;
    }

你可能感兴趣的:(Yii2 CSRF)