Yii2에서 쿠키의 실현 원리를 깊이 이해하다

5066 단어
유지보수를 편리하게 하기 위해 Yii는 쿠키의 조작 방법을 봉인했고 일반적인 쿠키 읽기와 쓰기를 실현한 토대에서 쿠키 검증 기능을 추가하여 쿠키가 클라이언트에서 수정되는 것을 방지했다.본고는 쿠키의 실현 과정을 상세하게 해석할 것이다.
참조 클래스: ii\base\Security - 해시 값 생성 및 검증 i\web\Cookie - 쿠키에 대한 캡슐화 i\web\Cookie Collection - i\web\Cookie의 집합 i\web\Request - 클라이언트가 제출한 쿠키 ii\web\Response 읽기 - 클라이언트에 쿠키 보내기
Yii에서 [[yi\web\Cookie]]는 쿠키를 대표하고 웹 요청과 응답은 [[yi\web\Request], [yi\web\Response]] 두 종류를 통해 처리되며 쿠키의 읽기와 발송도 그 중에서 이루어진다.Yii가 쿠키를 처리하는 전체 과정을 파악하기 위해 다음은 실제 장면을 통해 점차적으로 해석한다.
[[yi\web\Response]]를 사용하여 cookies 보내기
$cookies = Yii::$app->response->cookies;
$cookies->add(new \yii\web\Cookie([
    'name' => 'language',
    'value' => 'zh-CN',
]);
//     cookie
$cookies->remove('language');
//          
unset($cookies['language']);

코드를 통해 [[ii\web\Response]]가 하나의 cookies 속성을 통해 하나의 집합 클래스 [[[yi\web\CookieCollection]를 유지하는 것을 어렵지 않게 발견할 수 있습니다. 쿠키를 쓰는 방법은 이 집합에 [[[[yi\web\Cookie]]를 추가하는 것입니다.response를 보내기 전에 [[yii\web\Response::sendCookies()] 방법을 호출하고 모든 쿠키는 보내기 전에 해시 알고리즘 처리를 거쳐 새로운 값을 생성하여 쿠키가 클라이언트에서 수정할 수 없도록 합니다.
// Method in yii\web\Response
protected function sendCookies()
{
    if ($this->_cookies === null) {
        return;
    }
    $request = Yii::$app->getRequest();
    if ($request->enableCookieValidation) {
        if ($request->cookieValidationKey == '') {
            throw new InvalidConfigException(get_class($request) . '::cookieValidationKey must be configured with a secret key.');
        }
        $validationKey = $request->cookieValidationKey;
    }
    foreach ($this->getCookies() as $cookie) {
        $value = $cookie->value;
        if ($cookie->expire != 1  && isset($validationKey)) {
            //      
            $value = Yii::$app->getSecurity()->hashData(serialize([$cookie->name, $value]), $validationKey);
        }
        setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
    }
}

처리된 쿠키 형식은 다음과 같습니다. cd5c6293a1d65b62a2acdd426e230b588fda5a9e546f7d874d1b68e54642fcb1a%3A2%3A%7Bi%3A0%3Bs%3A8%3A%22language%22%2%3Bi%3A1%3Bs%3A5%3A%22zh-CN%2%3B%7D7D
해시 처리된 쿠키가 클라이언트에서 수정되면 ii\web\Request에서 필터링됩니다.
[[Yi\web\Request]]를 사용하여 cookies 읽기
$cookies = Yii::$app->request->cookies;

//      "language" cookie   ,     ,     "en"
$language = $cookies->getValue('language', 'en');

//           "language" cookie   
if (($cookie = $cookies->get('language')) !== null) {
    $language = $cookie->value;
}

//    $cookies      
if (isset($cookies['language'])) {
    $language = $cookies['language']->value;
}

//         "language"   cookie
if ($cookies->has('language')) ...
if (isset($cookies['language'])) ...

[[yi\web\Response]]와 마찬가지로 [yi\web\Request]도 cookies를 통해 Cookie Collection을 유지하고 서버에서 받은 모든 cookie는 검증된 후에 cookies에 넣어 읽을 수 있도록 합니다.
// Method in yii\web\Request
protected function loadCookies()
{
    $cookies = [];
    if ($this->enableCookieValidation) {
        if ($this->cookieValidationKey == '') {
            throw new InvalidConfigException(get_class($this) . '::cookieValidationKey must be configured with a secret key.');
        }
        foreach ($_COOKIE as $name => $value) {
            if (!is_string($value)) {
                continue;
            }
            //     
            $data = Yii::$app->getSecurity()->validateData($value, $this->cookieValidationKey);
            if ($data === false) {
                continue;
            }
            $data = @unserialize($data);
            if (is_array($data) && isset($data[0], $data[1]) && $data[0] === $name) {
                $cookies[$name] = new Cookie([
                    'name' => $name,
                    'value' => $data[1],
                    'expire' => null,
                ]);
            }
        }
    } else {
        foreach ($_COOKIE as $name => $value) {
            $cookies[$name] = new Cookie([
                'name' => $name,
                'value' => $value,
                'expire' => null,
            ]);
        }
    }

    return $cookies;
}

더.
  • 쿠키 인증을 닫으려면 [[yii\web\Request::enable CookieValidation]]을false로 설정하고 그러지 마십시오.
  • 요청한 쿠키가 검증되지 않았음에도 불구하고 $_COOKIE로 검증되지 않은 쿠키에 접근할 수 있습니다.
  • XSS 공격을 방지하기 위해 [[yii\web\Cookie]]에서 기본적으로 httpOnly를 엽니다. 이 때 쿠키는 자바스크립트에 접근할 수 없습니다. 닫으려면 httpOnly를false로 설정하십시오.
  • $cookie = new \yii\web\Cookie([
        'name' => 'language',
        'value' => 'zh-CN',
        'httpOnly' => false,
    ])
    

    참조 문서:https://github.com/yiisoft/yii2/blob/master/docs/guide/runtime-sessions-cookies.md

    좋은 웹페이지 즐겨찾기