docs

Various Yii 3.0 related documentation

View the Project on GitHub yiisoft/docs

Cookies

Cookies are for persisting data between requests by sending it to the client browser using HTTP headers. The client sends data back to server in request headers thus cookies are handy to store small amounts of data, such as tokens or flags.

Reading cookies

You could obtain Cookie values from server request that’s available as route handler (such as controller action) argument:

private function actionProfile(\Psr\Http\Message\ServerRequestInterface $request)
{
    $cookieValues = $request->getCookieParams();
    $cookieValue = $cookieValues['cookieName'] ?? null;
    // ...
}

Sending cookies

Since sending cookies is, in fact, sending a header but since forming the header isn’t trivial, there is \Yiisoft\Cookies\Cookie class to help with it:

$cookie = (new \Yiisoft\Cookies\Cookie('cookieName', 'value'))
    ->withPath('/')
    ->withDomain('yiiframework.com')
    ->withHttpOnly(true)
    ->withSecure(true)
    ->withSameSite(\Yiisoft\Cookies\Cookie::SAME_SITE_STRICT)
    ->withMaxAge(new \DateInterval('P7D'));

    return $cookie->addToResponse($response);

After forming a cookie call addToResponse() passing an instance of \Psr\Http\Message\ResponseInterface to add corresponding HTTP headers to it.

Signing and encrypting cookies

To prevent the substitution of the cookie value, the package provides two implementations:

Yiisoft\Cookies\CookieSigner - signs each cookie with a unique prefix hash based on the value of the cookie and a secret key. Yiisoft\Cookies\CookieEncryptor - encrypts each cookie with a secret key.

Encryption is more secure than signing, but has less performance.

$cookie = new \Yiisoft\Cookies\Cookie('identity', 'identityValue');

// The secret key used to sign and validate cookies.
$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';

$signer = new \Yiisoft\Cookies\CookieSigner($key);
$encryptor = new \Yiisoft\Cookies\CookieEncryptor($key);

$signedCookie = $signer->sign($cookie);
$encryptedCookie = $encryptor->encrypt($cookie);

To validate and get back the pure value, use the validate() and decrypt() method.

$cookie = $signer->validate($signedCookie);
$cookie = $encryptor->decrypt($encryptedCookie);

If the cookie value is tampered with or hasn’t been signed/encrypted before, a \RuntimeException will be thrown. Therefore, if you aren’t sure that the cookie value was signed/encrypted earlier, first use the isSigned() and isEncrypted() methods, respectively.

if ($signer->isSigned($cookie)) {
    $cookie = $signer->validate($cookie);
}

if ($encryptor->isEncrypted($cookie)) {
    $cookie = $encryptor->decrypt($cookie);
}

It makes sense to sign or encrypt the value of a cookie if you store important data that a user shouldn’t change.

Automating encryption and signing

To automate the encryption/signing and decryption/validation of cookie values, use an instance of Yiisoft\Cookies\CookieMiddleware, which is PSR-15 middleware.

This middleware provides the following features:

In order for the middleware to know which values of which cookies need to be encrypted/signed, an array of settings must be passed to its constructor. The array keys are cookie name patterns and values are constant values of CookieMiddleware::ENCRYPT or CookieMiddleware::SIGN.

use Yiisoft\Cookies\CookieMiddleware;

$cookiesSettings = [
    // Exact match with the name `identity`.
    'identity' => CookieMiddleware::ENCRYPT,
    // Matches any number from 1 to 9 after the underscore.
    'name_[1-9]' => CookieMiddleware::SIGN,
    // Matches any string after the prefix, including an
    // empty string, except for the delimiters "/" and "\".
    'prefix*' => CookieMiddleware::SIGN,
];

For more information on using the wildcard pattern, see the yiisoft/strings package.

Creating and using middleware:

/**
 * @var \Psr\Http\Message\ServerRequestInterface $request
 * @var \Psr\Http\Server\RequestHandlerInterface $handler
 * @var \Psr\Log\LoggerInterface $logger
 */

// The secret key used to sign and validate cookies.
$key = '0my1xVkjCJnD_q1yr6lUxcAdpDlTMwiU';
$signer = new \Yiisoft\Cookies\CookieSigner($key);
$encryptor = new \Yiisoft\Cookies\CookieEncryptor($key);

$cookiesSettings = [
    'identity' => \Yiisoft\Cookies\CookieMiddleware::ENCRYPT,
    'session' => \Yiisoft\Cookies\CookieMiddleware::SIGN,
];

$middleware = new \Yiisoft\Cookies\CookieMiddleware(
    $logger
    $encryptor,
    $signer,
    $cookiesSettings,
);

// The cookie parameter values from the request are decrypted/validated.
// The cookie values are encrypted/signed, and appended to the response.
$response = $middleware->process($request, $handler);

If the $cookiesSettings array is empty, no cookies will be encrypted and signed.

Cookies security

You should configure each cookie to be secure. Important security settings are: