>  기사  >  PHP 프레임워크  >  yii csrf 란 무엇입니까?

yii csrf 란 무엇입니까?

(*-*)浩
(*-*)浩원래의
2019-12-04 11:49:292507검색

Cross-site request forgery(영어: Cross-site request forgery), 원클릭 공격 또는 세션 라이딩이라고도 하며 일반적으로 CSRF 또는 XSRF로 축약됩니다. 은 현재 로그인되어 있는 웹 애플리케이션에서 사용자가 의도하지 않은 작업을 수행하도록 강요하는 공격 방법입니다. 간단히 말해, 교차 사이트 요청 공격은 공격자가 기술적 수단을 사용하여 사용자의 브라우저를 속여 웹 사이트에 액세스하는 것입니다. 그는 인증된 웹사이트를 사용하고 일부 작업(예: 이메일 보내기, 메시지 보내기, 심지어 돈 이체 및 상품 구매와 같은 자산 작업)을 수행했다는 사실을 알 수 있습니다. (추천 학습:##yii 프레임워크)#🎜🎜 ## 🎜🎜 ## 🎜🎜#브라우저가 인증되었으므로 접속하는 웹사이트는 실제 사용자 작업으로 간주됩니다.

yii csrf 란 무엇입니까?이것은 웹의 사용자 인증 취약점을 악용합니다. 단순 인증은 요청이 특정 사용자의 브라우저에서 오는지 여부만 보장할 수 있지만 요청 자체가 사용자에 의해 자발적으로 이루어졌다는 것을 보장할 수는 없습니다. 사용자.

yii2의 csrf, 검증 메커니즘에 대한 간략한 소개는 다음과 같습니다.

csrf 검증에 사용되는 토큰 값을 가져옵니다. csrf에 사용되는 토큰이 존재하는지 확인하고, 존재하지 않으면 generateCsrfToken()을 사용하여 생성합니다.

webController의 beforeAction() 메서드에 csrf를 확인하는 데 사용되는 Yii::$app->getRequest()->validateCsrfToken() 판단이 있는지 확인합니다.

일반적으로 yii2의 csrf에 대한 이해는 Yii::$app->request->getCsrfToken(); 자, getCsrfToken()부터 시작하겠습니다. 이 메소드는 yiiwebRequest.php에 있습니다:

/**
 * Returns the token used to perform CSRF validation.
 * 返回用于执行CSRF验证的token
 * This token is a masked version of [[rawCsrfToken]] to prevent [BREACH attacks](http://breachattack.com/).
 * This token may be passed along via a hidden field of an HTML form or an HTTP header value
 * to support CSRF validation.
 * @param boolean $regenerate whether to regenerate CSRF token. When this parameter is true, each time
 * this method is called, a new CSRF token will be generated and persisted (in session or cookie).
 * @return string the token used to perform CSRF validation.
 */
public function getCsrfToken($regenerate = false)
{
    if ($this->_csrfToken === null || $regenerate) {
        if ($regenerate || ($token = $this->loadCsrfToken()) === null) {    //loadCsrfToken()就是在cookie或者session中获取token值
            $token = $this->generateCsrfToken();        //如果token为空则调用generateCsrfToken()去生成
        }
        // the mask doesn't need to be very random
        $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.';
        $mask = substr(str_shuffle(str_repeat($chars, 5)), 0, static::CSRF_MASK_LENGTH);
        // The + sign may be decoded as blank space later, which will fail the validation
        $this->_csrfToken = str_replace('+', '.', base64_encode($mask . $this->xorTokens($token, $mask)));
    }

    return $this->_csrfToken;
}

/**
 * Loads the CSRF token from cookie or session.
 * @return string the CSRF token loaded from cookie or session. Null is returned if the cookie or session
 * does not have CSRF token.
 */
protected function loadCsrfToken()
{
    if ($this->enableCsrfCookie) {
        return $this->getCookies()->getValue($this->csrfParam);         //cookie中获取csrf的token 
    } else {
        return Yii::$app->getSession()->get($this->csrfParam);          //session中获取csrf的token
    }
}

/**
 * Creates a cookie with a randomly generated CSRF token.
 * Initial values specified in [[csrfCookie]] will be applied to the generated cookie.
 * @param string $token the CSRF token
 * @return Cookie the generated cookie
 * @see enableCsrfValidation
 */
protected function createCsrfCookie($token)
{
    $options = $this->csrfCookie;
    $options['name'] = $this->csrfParam;
    $options['value'] = $token;
    return new Cookie($options);
}

/**
 * Generates  an unmasked random token used to perform CSRF validation.
 * @return string the random token for CSRF validation.
 */
protected function generateCsrfToken()
{
    $token = Yii::$app->getSecurity()->generateRandomString();      //生成随机的安全字符串
    if ($this->enableCsrfCookie) {
        $cookie = $this->createCsrfCookie($token);                  //createCsrfCookie()用于生成csrf的key=>value形式的token
        Yii::$app->getResponse()->getCookies()->add($cookie);       //将生成key=>value保存到cookies 
    } else {
        Yii::$app->getSession()->set($this->csrfParam, $token);     //将csrf的token存在session中
    }
    return $token;
}

/**
 * 每次调用控制器中的方法的时候都会调用下面的Yii::$app->getRequest()->validateCsrfToken()验证
 * @inheritdoc
 */
public function beforeAction($action)
{
    if (parent::beforeAction($action)) {
        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;
    } else {
        return false;
    }
}


/**
 * 校验方法
 * Performs the CSRF validation.
 *
 * This method will validate the user-provided CSRF token by comparing it with the one stored in cookie or session.
 * This method is mainly called in [[Controller::beforeAction()]].
 *
 * Note that the method will NOT perform CSRF validation if [[enableCsrfValidation]] is false or the HTTP method
 * is among GET, HEAD or OPTIONS.
 *
 * @param string $token the user-provided CSRF token to be validated. If null, the token will be retrieved from
 * the [[csrfParam]] POST field or HTTP header.
 * This parameter is available since version 2.0.4.
 * @return boolean whether CSRF token is valid. If [[enableCsrfValidation]] is false, this method will return true.
 */
public function validateCsrfToken($token = null)
{
    $method = $this->getMethod();
    // only validate CSRF token on non-"safe" methods http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1
    if (!$this->enableCsrfValidation || in_array($method, ['GET', 'HEAD', 'OPTIONS'], true)) {
        return true;
    }

    $trueToken = $this->loadCsrfToken();

    if ($token !== null) {
        return $this->validateCsrfTokenInternal($token, $trueToken);
    } else {
        return $this->validateCsrfTokenInternal($this->getBodyParam($this->csrfParam), $trueToken)
            || $this->validateCsrfTokenInternal($this->getCsrfTokenFromHeader(), $trueToken); 
            //getCsrfTokenFromHeader()这个我也不太理解,还请指点一下
    }
}

/**
 * @return string the CSRF token sent via [[CSRF_HEADER]] by browser. Null is returned if no such header is sent.
 */
public function getCsrfTokenFromHeader()
{
    $key = 'HTTP_' . str_replace('-', '_', strtoupper(static::CSRF_HEADER));
    return isset($_SERVER[$key]) ? $_SERVER[$key] : null;
}

/**
 * Validates CSRF token
 *
 * @param string $token
 * @param string $trueToken
 * @return boolean
 */
private function validateCsrfTokenInternal($token, $trueToken)
{
    $token = base64_decode(str_replace('.', '+', $token));      //解码从客户端获取的csrf的token
    $n = StringHelper::byteLength($token);
    if ($n <= static::CSRF_MASK_LENGTH) {
        return false;
    }
    $mask = StringHelper::byteSubstr($token, 0, static::CSRF_MASK_LENGTH);
    $token = StringHelper::byteSubstr($token, static::CSRF_MASK_LENGTH, $n - static::CSRF_MASK_LENGTH);
    $token = $this->xorTokens($mask, $token);

    return $token === $trueToken;       //验证从客户端获取的csrf的token和真实的token是否相等
}

위 내용은 yii csrf 란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.