Spec-Zone.ru › Yii 2.0

Сессии и куки

  1. Сессии
  2. Куки

Сессии и куки позволяют сохранять данные между несколькими запросами пользователя. В чистом PHP к ним можно обратиться через глобальные переменные $_SESSION и $_COOKIE соответственно. Yii инкапсулирует сессии и куки как объекты, что позволяет получать доступ к ним объектно-ориентированным способом с дополнительными полезными улучшениями.

Сессии

Как и запросы и ответы, вы можете получить доступ к сессиям через session компонент приложения, который по умолчанию является экземпляром yii\web\Session.

Открытие и закрытие сессий

Для открытия и закрытия сессии можно выполнить следующие действия:

$session = Yii::$app->session;

// check if a session is already open
if ($session->isActive) ...

// open a session
$session->open();

// close a session
$session->close();

// destroys all data registered to a session.
$session->destroy();

Вы можете вызывать open() и close() несколько раз без ошибок; внутренне методы сначала проверяют, открыта ли сессия.

Доступ к данным сессии

Для доступа к данным, хранящимся в сессии, можно выполнить следующие действия:

$session = Yii::$app->session;

// get a session variable. The following usages are equivalent:
$language = $session->get('language');
$language = $session['language'];
$language = isset($_SESSION['language']) ? $_SESSION['language'] : null;

// set a session variable. The following usages are equivalent:
$session->set('language', 'en-US');
$session['language'] = 'en-US';
$_SESSION['language'] = 'en-US';

// remove a session variable. The following usages are equivalent:
$session->remove('language');
unset($session['language']);
unset($_SESSION['language']);

// check if a session variable exists. The following usages are equivalent:
if ($session->has('language')) ...
if (isset($session['language'])) ...
if (isset($_SESSION['language'])) ...

// traverse all session variables. The following usages are equivalent:
foreach ($session as $name => $value) ...
foreach ($_SESSION as $name => $value) ...

Информация: При обращении к данным сессии через компонент session, сессия будет автоматически открыта, если это еще не сделано. Это отличается от доступа к данным сессии через $_SESSION, который требует явного вызова session_start().

При работе с данными сессии, являющимися массивами, компонент session имеет ограничение, которое не позволяет напрямую изменять элемент массива. Например,

$session = Yii::$app->session;

// the following code will NOT work
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;

// the following code works:
$session['captcha'] = [
    'number' => 5,
    'lifetime' => 3600,
];

// the following code also works:
echo $session['captcha']['lifetime'];

Для решения этой проблемы можно использовать один из следующих способов:

$session = Yii::$app->session;

// directly use $_SESSION (make sure Yii::$app->session->open() has been called)
$_SESSION['captcha']['number'] = 5;
$_SESSION['captcha']['lifetime'] = 3600;

// get the whole array first, modify it and then save it back
$captcha = $session['captcha'];
$captcha['number'] = 5;
$captcha['lifetime'] = 3600;
$session['captcha'] = $captcha;

// use ArrayObject instead of array
$session['captcha'] = new \ArrayObject;
...
$session['captcha']['number'] = 5;
$session['captcha']['lifetime'] = 3600;

// store array data by keys with a common prefix
$session['captcha.number'] = 5;
$session['captcha.lifetime'] = 3600;

Для лучшей производительности и удобочитаемости кода рекомендуется последний метод. То есть вместо хранения массива как одной переменной сессии, вы храните каждый элемент массива как отдельную переменную сессии, которая использует тот же префикс ключа, что и другие элементы массива.

Настройка хранения сессий

По умолчанию класс yii\web\Session хранит данные сессии как файлы на сервере. Yii также предоставляет следующие классы сессий, реализующие различные методы хранения сессий:

  • yii\web\DbSession: хранит данные сессий в таблице базы данных.
  • yii\web\CacheSession: хранит данные сессии в кэше с помощью настроенного компонента кэша.
  • yii\redis\Session: хранит данные сессий, используя redis в качестве хранилища.
  • yii\mongodb\Session: хранит данные сессии в MongoDB.

Все эти классы сессий поддерживают одинаковый набор API-методов. В результате, вы можете переключаться на другой класс хранения сессий без необходимости модифицировать код приложения, использующий сессии.

Примечание: Если вы хотите получить доступ к данным сессии через $_SESSION, используя пользовательское хранилище сессий, вы должны убедиться, что сессия уже запущена методом yii\web\Session::open(). Это связано с тем, что обработчики пользовательского хранилища сессий регистрируются в этом методе.

Чтобы узнать, как настроить и использовать эти классы компонентов, пожалуйста, обратитесь к их API-документации. Ниже приведен пример того, как настроить yii\web\DbSession в конфигурации приложения для использования таблицы базы данных для хранения сессий:

return [
    'components' => [
        'session' => [
            'class' => 'yii\web\DbSession',
            // 'db' => 'mydb',  // the application component ID of the DB connection. Defaults to 'db'.
            // 'sessionTable' => 'my_session', // session table name. Defaults to 'session'.
        ],
    ],
];

Вам также необходимо создать следующую таблицу базы данных для хранения данных сессий:

CREATE TABLE session
(
    id CHAR(40) NOT NULL PRIMARY KEY,
    expire INTEGER,
    data BLOB
)

где 'BLOB' относится к типу BLOB в вашей базе данных. Ниже приведены типы BLOB, которые могут быть использованы для некоторых популярных баз данных:

  • MySQL: LONGBLOB
  • PostgreSQL: BYTEA
  • MSSQL: BLOB

Примечание: В зависимости от настройки php.ini параметра session.hash_function, возможно, вам потребуется изменить длину столбца id. Например, если session.hash_function=sha256, вы должны использовать длину 64 вместо 40.

В качестве альтернативы это можно сделать с помощью следующей миграции:

<?php

use yii\db\Migration;

class m170529_050554_create_table_session extends Migration
{
    public function up()
    {
        $this->createTable('{{%session}}', [
            'id' => $this->char(64)->notNull(),
            'expire' => $this->integer(),
            'data' => $this->binary()
        ]);
        $this->addPrimaryKey('pk-id', '{{%session}}', 'id');
    }

    public function down()
    {
        $this->dropTable('{{%session}}');
    }
}

Данные флэш-памяти

Данные флэш-памяти — это особый вид данных сессии, которые, будучи установлены в одном запросе, будут доступны только в следующем запросе и будут автоматически удалены после этого. Данные флэш-памяти чаще всего используются для реализации сообщений, которые должны быть показаны пользователям только один раз, например, сообщение подтверждения, отображаемое после успешной отправки формы пользователем.

Вы можете установить и получить доступ к данным флэш-памяти через компонент приложения session. Например,

$session = Yii::$app->session;

// Request #1
// set a flash message named as "postDeleted"
$session->setFlash('postDeleted', 'You have successfully deleted your post.');

// Request #2
// display the flash message named "postDeleted"
echo $session->getFlash('postDeleted');

// Request #3
// $result will be false since the flash message was automatically deleted
$result = $session->hasFlash('postDeleted');

Как и обычные данные сессии, вы можете хранить любые данные в виде данных флэш-памяти.

При вызове yii\web\Session::setFlash(), он перезапишет любые существующие данные флэш-памяти с тем же именем. Чтобы добавить новые данные флэш-памяти к существующему сообщению с тем же именем, можно вызвать yii\web\Session::addFlash() вместо этого. Например:

$session = Yii::$app->session;

// Request #1
// add a few flash messages under the name of "alerts"
$session->addFlash('alerts', 'You have successfully deleted your post.');
$session->addFlash('alerts', 'You have successfully added a new friend.');
$session->addFlash('alerts', 'You are promoted.');

// Request #2
// $alerts is an array of the flash messages under the name of "alerts"
$alerts = $session->getFlash('alerts');

Примечание: Старайтесь не использовать yii\web\Session::setFlash() вместе с yii\web\Session::addFlash() для данных флэш-памяти с одинаковым именем. Это связано с тем, что последний метод автоматически преобразует данные флэш-памяти в массив, чтобы добавить новые данные флэш-памяти с тем же именем. В результате, когда вы вызываете yii\web\Session::getFlash(), вы можете иногда получать массив, а иногда строку, в зависимости от порядка вызова этих двух методов.

Подсказка: Для отображения сообщений флэш-памяти вы можете использовать виджет bootstrap Alert следующим образом:

echo Alert::widget([
   'options' => ['class' => 'alert-info'],
   'body' => Yii::$app->session->getFlash('postDeleted'),
]);

Куки

Yii представляет каждый куки как объект yii\web\Cookie. И yii\web\Request, и yii\web\Response поддерживают коллекцию куки через свойство с именем cookies. Коллекция куки в первом случае представляет куки, отправленные в запросе, а во втором — куки, которые будут отправлены пользователю.

Часть приложения, непосредственно работающая с запросом и ответом, — это контроллер. Поэтому куки должны читаться и отправляться в контроллере.

Чтение куки

Вы можете получить куки в текущем запросе, используя следующий код:

// get the cookie collection (yii\web\CookieCollection) from the "request" component
$cookies = Yii::$app->request->cookies;

// get the "language" cookie value. If the cookie does not exist, return "en" as the default value.
$language = $cookies->getValue('language', 'en');

// an alternative way of getting the "language" cookie value
if (($cookie = $cookies->get('language')) !== null) {
    $language = $cookie->value;
}

// you may also use $cookies like an array
if (isset($cookies['language'])) {
    $language = $cookies['language']->value;
}

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

Отправка куки

Вы можете отправить куки пользователям, используя следующий код:

// get the cookie collection (yii\web\CookieCollection) from the "response" component
$cookies = Yii::$app->response->cookies;

// add a new cookie to the response to be sent
$cookies->add(new \yii\web\Cookie([
    'name' => 'language',
    'value' => 'zh-CN',
]));

// remove a cookie
$cookies->remove('language');
// equivalent to the following
unset($cookies['language']);

Помимо свойств имени и значения, показанных в приведенных выше примерах, класс yii\web\Cookie также определяет другие свойства для полного представления всех доступных данных о куки, таких как домен, срок действия. Вы можете настроить эти свойства по мере необходимости для подготовки куки и затем добавить его в коллекцию куки ответа.

Примечание: Для повышения безопасности значение по умолчанию для yii\web\Cookie::$httpOnly установлено в true. Это помогает снизить риск доступа скрипта на стороне клиента к защищенному куки (если браузер его поддерживает). Вы можете ознакомиться со статьей в вики httpOnly для получения более подробной информации.

Проверка куки

При чтении и отправке куки через компоненты request и response, как показано в последних двух разделах, вы получаете дополнительную безопасность проверки куки, которая защищает куки от изменения на стороне клиента. Это достигается путем подписи каждого куки строкой хэша, что позволяет приложению определить, был ли куки изменён на стороне клиента. Если да, куки НЕ будет доступен через коллекцию cookie компонента request.

Примечание: Проверка куки защищает только значения куки от изменения. Если куки не проходит проверку, вы всё равно можете получить к нему доступ через $_COOKIE. Это связано с тем, что сторонние библиотеки могут манипулировать куки своими методами, не вовлекая проверку куки.

Проверка куки включена по умолчанию. Вы можете отключить её, установив свойство yii\web\Request::$enableCookieValidation в значение false, хотя настоятельно рекомендуется этого не делать.

Примечание: Куки, которые непосредственно считываются/отправляются через $_COOKIE и setcookie(), НЕ будут проверены.

При использовании проверки куки вы должны указать yii\web\Request::$cookieValidationKey, который будет использоваться для генерации упомянутых строк хэша. Вы можете сделать это, настроив компонент request в конфигурации приложения:

return [
    'components' => [
        'request' => [
            'cookieValidationKey' => 'fill in a secret key here',
        ],
    ],
];

Информация: cookieValidationKey имеет важное значение для безопасности вашего приложения. Его должны знать только доверенные лица. Не храните его в системе управления версиями.

© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-runtime-sessions-cookies.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API