Мы принимаем к оплате:

«Подарочный сертификат» от нашего Учебного Центра – это лучший подарок для тех, кто Вам дорог! Оплате обучение и подарите Вашим родным и близким обучение по любому из курсов!!!

«Сертификат на повторное обучение» дает возможность повторно пройти обучение в нашем Учебном Центре со скидкой 1000 рублей!

А также:


Php как работают сессии


PHP: Основы использования - Manual

Сессии являются простым способом хранения информации для отдельных пользователей с уникальным идентификатором сессии. Это может использоваться для сохранения состояния между запросами страниц. Идентификаторы сессий обычно отправляются браузеру через сессионный cookie и используются для получения имеющихся данных сессии. Отсутствие идентификатора сессии или сессионного cookie сообщает PHP о том, что необходимо создать новую сессию и сгенерировать новый идентификатор сессии.

Сессии используют простую технологию. Когда сессия создана, PHP будет либо получать существующую сессию, используя переданный идентификатор (обычно из сессионного cookie) или, если ничего не передавалось, будет создана новая сессия. PHP заполнит суперглобальную переменную $_SESSION сессионной информацией после того, как будет запущена сессия. Когда PHP завершает работу, он автоматически сериализует содержимое суперглобальной переменной $_SESSION и отправит для сохранения, используя сессионный обработчик для записи сессии.

По умолчанию PHP использует внутренний обработчик files для сохранения сессий, который установлен в INI-переменной session.save_handler. Этот обработчик сохраняет данные на сервере в директории, указанной в конфигурационной директиве session.save_path.

Сессии могут запускаться вручную с помощью функции session_start(). Если директива session.auto_start установлена в 1, сессия автоматически запустится, в начале запроса.

Сессия обычно завершает свою работу, когда PHP заканчивает исполнять скрипт, но может быть завершена и вручную с помощью функции session_write_close().

Пример #1 Регистрация переменной с помощью $_SESSION.

Пример #2 Отмена объявления переменной с помощью $_SESSION.

Предостережение

НЕ ОЧИЩАЙТЕ $_SESSION целиком, используя unset($_SESSION), так как это отключит возможность регистрации сессионных переменных через суперглобальную переменную $_SESSION.

Внимание

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

Замечание:

Сессии, использующие файлы (по умолчанию в PHP), блокируют файл сессии сразу при открытии сессии функцией session_start() или косвенно при указании session.auto_start. После блокировки, ни один другой скрипт не может получить доступ к этому же файлу сессии, пока он не будет закрыт или при завершении скрипта или при вызове функции session_write_close().

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

Работа с сессиями PHP

Многие начинающие не понимают, что когда они видят страницу сайта в своем браузере, PHP скрипт уже давно отработал и забыл о нас.

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

Однако, такой механизм очень нужен, хотя бы для того, чтобы запоминать выбор пользователя или то, что пользователь был авторизован.

На помощь программистам приходят такие механизмы как сессии и cookie (куки).

Что такое сессии в PHP?

Сессия - это механизм PHP, который позволяет хранить данные для конкретного пользователя между запусками скрипта.

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

С помощью сессии можно реализовать авторизацию пользователей, корзину интернет-магазина и другое.

Инициализируем сессию

Чтобы записать что-то в сессию ее сначала нужно инициализировать с помощью функции session_start():

Обратите внимание на то, что в одном скрипте сессия должна инициализироваться только один раз, иначе скрипт выдаст ошибку.

Пишем в сессии

После инициализации мы можем записать что-нибудь в сессию.

Сделать это не сложно:

Читаем из сессий

После того, как мы что-то записали в сессию, мы можем это оттуда извлечь:

Возможные проблемы

Данный материал есть также в виде видео: https://youtu.be/rIHGX-XTLpw

Основная проблема при работе с сессией следующая: нельзя делать никакого вывода в браузер до окончания работы с сессиями.

Что такое вывод в браузер?

Это любой символ до

Удалении переменных из сессии

Переменную сессии можно удалять с помощью функции unset:

Завершение сессии

Если же вам нужно удалить все переменные сессии для данного пользователя, то вместо unset следует воспользоваться функцией session_destroy() (ее можно вызывать только тогда, когда сессия запущена через session_start):

Мы рассмотрели принудительное завершение сессии. Однако сессия может завершится сама в двух следующих случаях: при закрытии браузера пользователем или по истечении определенного времени, во время которого пользователь не совершает никаких действий на странице (по умолчанию это время около 15-25 минут).

Какие задачи решает сессия

Стандартные задачи, которые решают с помощью сессии, это корзина интернет-магазина, форма для заполнения пользователем, разбитая на несколько страниц сайта (на первой мы спрашиваем имя, на второй email и т.д.), авторизация пользователей на PHP.

Сессии и формы

Поможет с решением задач: https://youtu.be/GDFYbddLH5A

Подводные камни использования сессий в PHP

Приветствую, уважаемое сообщество. Прежде всего, хочу поблагодарить за очень полезный ресурс. Не раз находил здесь множество интересных идей и практических советов. Цель этой статьи — осветить подводные камни использования сессий в PHP. Конечно, есть документация по PHP и масса примеров, и данная статья не претендует на полное руководство. Она призвана раскрыть некоторые ньюансы работы с сессиями и оградить разработчиков от ненужной траты времени. Самым распространенным примером использования сессий является, конечно, авторизация пользователей. Начнем с самой базовой реализации, чтобы последовательно развивать ее по мере появления новых задач. (В целях экономии места и времени ограничимся в примерах только самими функциями работы с сессиями, вместо того, чтобы строить здесь полноценное тестовое приложение с красивой иерархией классов, исчерпывающей обработкой ошибок и прочими правильными штуками). function startSession() { // Если сессия уже была запущена, прекращаем выполнение и возвращаем TRUE // (параметр session.auto_start в файле настроек php.ini должен быть выключен - значение по умолчанию) if ( session_id() ) return true; else return session_start(); // Примечание: До версии 5.3.0 функция session_start()возвращала TRUE даже в случае ошибки. // Если вы используете версию ниже 5.3.0, выполняйте дополнительную проверку session_id() // после вызова session_start() } function destroySession() { if ( session_id() ) { // Если есть активная сессия, удаляем куки сессии, setcookie(session_name(), session_id(), time()-60*60*24); // и уничтожаем сессию session_unset(); session_destroy(); } }

Примечание: Подразумевается, что базовые знания о сессиях PHP у читателя имеются, поэтому принцип работы функций session_start() и session_destroy() освещать здесь не будем. Задачи верстки формы входа и аутентификации пользователя не относятся к теме статьи, поэтому их мы также опустим. Напомню только, что для идентификации пользователя в каждом последующем запросе, нам необходимо в момент успешного входа сохранить в сессионной переменной (с именем userid, например) идентификатор пользователя, который будет доступен во всех последующих запросах в пределах жизни сессии. Также необходимо реализовать обработку результата нашей функции startSession(). Если функция вернула FALSE — отобразить в браузере форму входа. Если функция вернула TRUE, и сессионная переменная, содержащая идентификатор авторизованного пользователя (в нашем случае — userid), существует — отобразить страницу авторизованного пользователя (подробнее об обработке ошибок см. дополнение от 2013-06-07 в разделе о сессионных переменных).

Пока все понятно. Вопросы начинаются, когда требуется реализовать контроль отсутствия активности пользователя (session timeout), дать возможность одновременной работы в одном браузере нескольких пользователей, а также защитить сессии от несанкционированного использования. Об этом и пойдет речь ниже.
Контроль отсутствия активности пользователя встроенными средствами PHP
Первый вопрос, который часто возникает у разработчиков всевозможных консолей для пользователей — автоматическое завершение сеанса в случае отсутствия активности со стороны пользователя. Нет ничего проще, чем сделать это с помощью встроенных возможностей PHP. (Этот вариант не отличается особой надежностью и гибкостью, но рассмотрим его для полноты картины). function startSession() { // Таймаут отсутствия активности пользователя (в секундах) $sessionLifetime = 300; if ( session_id() ) return true; // Устанавливаем время жизни куки ini_set('session.cookie_lifetime', $sessionLifetime); // Если таймаут отсутствия активности пользователя задан, устанавливаем время жизни сессии на сервере // Примечание: Для production-сервера рекомендуется предустановить эти параметры в файле php.ini if ( $sessionLifetime ) ini_set('session.gc_maxlifetime', $sessionLifetime); if ( session_start() ) { setcookie(session_name(), session_id(), time()+$sessionLifetime); return true; } else return false; } Немного пояснений. Как известно, PHP определяет, какую именно сессию нужно запустить, по имени куки, передаваемом браузером в заголовке запроса. Браузер же, в свою очередь, получает этот куки от сервера, куда помещает его функция session_start(). Если время жизни куки в браузере истекло, он не будет передан в запросе, а значит PHP не сможет определить, какую сессию нужно запустить, и расценит это как создание новой сессии. Параметр настроек PHP session.gc_maxlifetime, который устанавливается равным нашему таймауту отсутствия активности пользователя, задает время жизни PHP-сессии и контролируется сервером. Работает контроль времени жизни сессии следующим образом (здесь рассматривается пример хранилища сессий во временных файлах как самый распространенный и установленный по умолчанию в PHP вариант). В момент создания новой сессии в каталоге, установленном как каталог для хранения сессий в параметре настроек PHP session.save_path, создается файл с именем sess_, где — идентификатор сессии. Далее, в каждом запросе, в момент запуска уже существующей сессии, PHP обновляет время модификации этого файла. Таким образом, в каждом следующем запросе PHP, путем разницы между текущим временем и временем последней модификации файла сессии, может определить, является ли сессия активной, или ее время жизни уже истекло. (Механизм удаления старых файлов сессий более подробно рассматривается в следующем разделе).

Примечание: Здесь следует отметить, что параметр session.gc_maxlifetime действует на все сессии в пределах одного сервера (точнее, в пределах одного главного процесса PHP). На практике это значит, что если на сервере работает несколько сайтов, и каждый из них имеет собственный таймаут отсутствия активности пользователей, то установка этого параметра на одном из сайтов приведет к его установке и для других сайтов. То же касается и shared-хостинга. Для избежания подобной ситуации используются отдельные каталоги сессий для каждого сайта в пределах одного сервера. Установка пути к каталогу сессий производится с помощью параметра session.save_path в файле настроек php.ini, или путем вызова функции ini_set(). После этого сессии каждого сайта будут храниться в отдельных каталогах, и параметр session.gc_maxlifetime, установленный на одном из сайтов, будет действовать только на его сессии. Мы не станем рассматривать этот случай подробно, тем более, что у нас в запасе есть более гибкий вариант контроля отсутствия активности пользователя.

Контроль отсутствия активности пользователя с помощью сессионных переменных
Казалось бы, предыдущий вариант при всей своей простоте (всего пару дополнительных строк кода) дает все, что нам нужно. Но что, если не каждый запрос можно расценивать как результат активности пользователя? Например, на странице установлен таймер, который периодически выполняет AJAX-запрос на получение обновлений от сервера. Такой запрос нельзя расценивать как активность пользователя, а значит автоматическое продление времени жизни сессии является не корректным в данном случае. Но мы знаем, что PHP обновляет время модификации файла сессии автоматически при каждом вызове функции session_start(), а значит любой запрос приведет к продлению времени жизни сессии, и таймаут отсутствия активности пользователя не наступит никогда. К тому же, последнее примечание из предыдущего раздела о тонкостях работы параметра session.gc_maxlifetime может показаться кому-то слишком запутанным и сложным в реализации. Для решения этой проблемы откажемся от использования встроенных механизмов PHP и введем несколько новых сессионных переменных, которые позволят нам контролировать время отсутствия активности пользователей самостоятельно. function startSession($isUserActivity=true) { $sessionLifetime = 300; if ( session_id() ) return true; // Устанавливаем время жизни куки до закрытия браузера (контролировать все будем на стороне сервера) ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; $t = time(); if ( $sessionLifetime ) { // Если таймаут отсутствия активности пользователя задан, // проверяем время, прошедшее с момента последней активности пользователя // (время последнего запроса, когда была обновлена сессионная переменная lastactivity) if ( isset($_SESSION['lastactivity']) && $t-$_SESSION['lastactivity'] >= $sessionLifetime ) { // Если время, прошедшее с момента последней активности пользователя, // больше таймаута отсутствия активности, значит сессия истекла, и нужно завершить сеанс destroySession(); return false; } else { // Если таймаут еще не наступил, // и если запрос пришел как результат активности пользователя, // обновляем переменную lastactivity значением текущего времени, // продлевая тем самым время сеанса еще на sessionLifetime секунд if ( $isUserActivity ) $_SESSION['lastactivity'] = $t; } } return true; } Подытожим. В каждом запросе мы проверяем, не достигнут ли таймаут с момента последней активности пользователя до текущего момента, и если он достигнут — уничтожаем сессию и прерываем выполнение функции, возвращая FALSE. Если же таймаут не достигнут, и в функцию передан параметр $isUserActivity со значением TRUE — обновляем время последней активности пользователя. Все, что нам остается сделать — это определять в вызывающем скрипте, является ли запрос результатом активности пользователя, и если нет — вызывать функцию startSession со значением параметра $isUserActivity, равным FALSE. Дополнение от 2013-06-07 Обработка результата функции sessionStart() В комментариях обратили внимание на то, что возврат FALSE не дает полного понимания причины ошибки, и это абсолютно справедливо. Я не стал публиковать здесь подробную обработку ошибок (объем статьи и так не маленький), поскольку это не относится напрямую к теме статьи. Но учитывая комментарии, внесу ясность. Как видно, функция sessionStart может вернуть FALSE в двух случаях. Либо сессию не удалось запустить из-за каких-то внутренних ошибок сервера (например, неправильные настройки сессий в php.ini), либо время жизни сессии истекло. В первом случае мы должны перебросить пользователя на страницу с ошибкой о том, что есть проблемы на сервере, и формой обращения в службу поддержки. Во втором случае мы должны перевести пользователя на форму входа и вывести в ней соответствующее сообщение о том, что время сессии истекло. Для этого нам необходимо ввести коды ошибок и возвращать вместо FALSE соответствующий код, а в вызывающем методе проверять его и действовать соответствующим образом. Теперь, даже если сессия на сервере по-прежнему существует, она будет уничтожена при первом же обращении к ней, если таймаут отсутствия активности пользователя истек. И это произойдет независимо от того, какое время жизни сессий установлено в глобальных настройках PHP.

Примечание: А что произойдет, если браузер был закрыт, и куки с именем сессии был автоматически уничтожен? Запрос к серверу при следующем открытии браузера не будет содержать куки сессии, и сервер не сможет открыть сессию и проверить таймаут отсутствия активности пользователя. Для нас это равносильно созданию новой сессии и никак не влияет на функционал и безопасность. Но возникает справедливый вопрос — а кто же тогда уничтожит старую сессию, если до сих пор ее уничтожали мы по истечении таймаута? Или она теперь будет висеть в каталоге сессий вечно? Для очистки старых сессий в PHP существует механизм под названием garbage collection. Он запускается в момент очередного запроса к серверу и чистит все старые сессии на основании даты последнего изменения файлов сессий. Но запуск механизма garbage collection происходит не при каждом запросе к серверу. Частота (а точнее, вероятность) запуска определяется двумя параметрами настроек session.gc_probability и session.gc_divisor. Результат от деления первого параметра на второй и есть вероятностью запуска механизма garbage collection. Таким образом, для того, чтобы механизм очистки сессий запускался при каждом запросе к севреру, эти параметры нужно установить в равные значения, например «1». Такой подход гарантирует чистоту каталога сессий, но, очевидно, является слишком накладным для сервера. Поэтому в production-системах по умолчанию устанавливается значение session.gc_divisor, равное 1000, что означает, что механизм garbage collection будет запускаться с вероятностью 1/1000. Если вы поэкспериментируете с этими настройками в своем файле php.ini, то сможете заметить, что в описанном выше случае, когда браузер закрывается и очищает все свои куки, в каталоге сессий какое-то время все еще остаются старые сессии. Но это не должно вас волновать, т.к. как уже было сказано, это ни коим образом не влияет на безопасность нашего механизма.

Дополнение от 2013-06-07
Предотвращение зависания скриптов из-за блокировки файла сессии
В комментариях подняли вопрос о зависании одновременно выполняющихся скриптов из-за блокировки файла сессии (как самый яркий вариант — long poll). Для начала отмечу, что эта проблема напрямую не зависит от загруженности сервера или количества пользователей. Конечно, чем больше запросов, тем медленнее выполняются скрипты. Но это коссвенная зависимость. Проблема появляется только в пределах одной сессии, когда серверу приходит несколько запросов от имени одного пользователя (например, один из них long poll, а остальные — обычные запросы). Каждый запрос пытается получить доступ к одному и тому же файлу сессии, и если предыдущий запрос не разблокировал файл, то последующий будет висеть в ожидании. Для сведения блокировки файлов сессий к минимуму настоятельно рекомендуется закрывать сессию путем вызова функции session_write_close() сразу после того, как выполнены все действия с сессионными переменными. На практике это означает, что не следует хранить в сессионных переменных все подряд и обращаться к ним на всем протяжении выполнения скрипта. А если и надо хранить в сессионных переменных какие-то рабочие данные, то считывать их сразу при старте сессии, сохранять в локальные переменные для последующего использования и закрывать сессию (имеется ввиду закрытие сессии с помощью функции session_write_close, а не уничтожение с помощью session_destroy). В нашем примере это означает, что сразу после открытия сессии, проверки времени ее жизни и существования авторизованного пользователя, мы должны считать и сохранить все дополнительные необходимые приложению сессионные переменные (если такие существуют), после чего закрыть сессию с помощью вызова session_write_close() и продолжить выполнение скрипта, будь то long poll или обычный запрос.
Защита сессий от несанкционированного использования
Представим себе ситуацию. Один из ваших пользователей цепляет троян, который грабит куки браузера (в котором хранится наша сессия) и отправляет его на указанный email. Злоумышленник получает куки и использует его для подделки запроса от имени нашего авторизованного пользователя. Сервер успешно принимает и обрабатывает этот запрос, как если бы он пришел от авторизованного пользователя. Если не реализована дополнительная проверка IP-адреса, такая атака приведет к успешному взлому аккаунта пользователя со всеми вытекающими последствиями. Почему это стало возможным? Очевидно, потому что имя и идентификатор сессии всегда одни и те же на все время жизни сессии, и если получить эти данные, то можно беспрепятственно слать запросы от имени другого пользователя (естественно, в пределах времени жизни этой сессии). Возможно, это не самый распространенный вид атак, но теоретически все выглядит вполне реализуемым, особенно учитывая, что подобному трояну даже не нужны права администратора, чтобы грабить куки браузера пользователя. Как же можно защититься от атак подобного рода? Опять-таки, очевидно, ограничив время жизни идентификатора сессии и периодически изменяя идентификатор в пределах одной сессии. Мы можем также изменять и имя сессии, полностью удаляя старую и создавая новую сессию, копируя в нее все сессионные переменные из старой. Но на суть подхода это не влияет, поэтому для простоты ограничимся только идентификатором сессии. Понятно, что чем меньше время жизни идентификатора сессии, тем меньше будет времени у злоумышленника, чтобы получить и применить куки для подделки запроса пользователя. В идеальном случае для каждого запроса должен использоваться новый идентификатор, что позволит свести к минимуму возможность использования чужой сессии. Но мы рассмотрим общий случай, когда время регенерации идентификатора сессии устанавливается произвольно. (Опустим ту часть кода, которая уже рассмотрена). function startSession($isUserActivity=true) { // Время жизни идентификатора сессии $idLifetime = 60; ... if ( $idLifetime ) { // Если время жизни идентификатора сессии задано, // проверяем время, прошедшее с момента создания сессии или последней регенерации // (время последнего запроса, когда была обновлена сессионная переменная starttime) if ( isset($_SESSION['starttime']) ) { if ( $t-$_SESSION['starttime'] >= $idLifetime ) { // Время жизни идентификатора сессии истекло // Генерируем новый идентификатор session_regenerate_id(true); $_SESSION['starttime'] = $t; } } else { // Сюда мы попадаем, если сессия только что создана // Устанавливаем время генерации идентификатора сессии в текущее время $_SESSION['starttime'] = $t; } } return true; } Итак, при создании новой сессии (которое происходит в момент успешного входа пользователя), мы устанавливаем сессионную переменную starttime, хранящую для нас время последней генерации идентификатора сессии, в значение, равное текущему времени сервера. Далее в каждом запросе мы проверяем, не прошло ли достаточно времени (idLifetime) с момента последней генерации идентификатора, и если прошло — генерируем новый. Таким образом, если в течение установленного времени жизни идентификатора злоумышленник, получивший куки авторизованного пользователя, не успеет им воспользоваться, поддельный запрос будет расценен сервером как неавторизованный, и злоумышленник попадет на страницу входа.

Примечание: Новый идентификатор сессии попадает в куки браузера при вызове функции session_regenerate_id(), которая отправляет новый куки, аналогично функции session_start(), поэтому нам нет необходимости обновлять куки самостоятельно.

Если мы хотим максимально обезопасить наши сессии, достаточно установить время жизни идентификатора в единицу или же вообще вынести функцию session_regenerate_id() за скобки и убрать все проверки, что приведет к регенерации идентификатора в каждом запросе. (Я не проверял влияние такого подхода на быстродействие, и могу только сказать, что функция session_regenerate_id(true) выполняет по сути всего 4 действия: генерация нового идентификатора, создание заголовка с куки сессии, удаление старого и создание нового файла сессии).

Лирическое отступление: Если троян окажется настолько умным, что не будет отправлять куки злоумышленнику, а сам организует отправку заранее подготовленного поддельного запроса сразу при получении куки, описанный выше метод, скорее всего, не сможет защитить от подобной атаки, потому что между временем получения трояном куки и отправкой поддельного запроса практически не будет разницы, и велика вероятность, что в этот момент не произойдет регенерации идентификатора сессии.

Возможность одновременной работы в одном браузере от имени нескольких пользователей
Последняя задача, которую хотелось бы рассмотреть — возможность одновременной работы в одном браузере нескольких пользователей. Эта возможность особенно полезна на этапе тестирования, когда нужно эмулировать одновременную работу пользователей, и желательно делать это в своем любимом браузере, а не использовать весь доступный арсенал или открывать несколько экземпляров браузера в режиме «инкогнито». В наших предыдущих примерах мы не задавали явно имя сессии, поэтому использовалось имя, установленное в PHP по умолчанию (PHPSESSID). Это значит, что все сессии, которые создавались нами до сих пор, отправляли браузеру куки под именем PHPSESSID. Очевидно, что если имя куки всегда одинаковое, то нет возможности в пределах одного браузера организовать две сессии с одинаковым именем. Но если бы мы для каждого пользователя использовали собственное имя сессии, то проблема была бы решена. Так и сделаем. function startSession($isUserActivity=true, $prefix=null) { ... if ( session_id() ) return true; // Если в параметрах передан префикс пользователя, // устанавливаем уникальное имя сессии, включающее этот префикс, // иначе устанавливаем общее для всех пользователей имя (например, MYPROJECT) session_name('MYPROJECT'.($prefix ? '_'.$prefix : '')); ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; ... } Теперь осталось позаботиться о том, чтобы вызывающий скрипт передавал в функцию startSession() уникальный префикс для каждого пользователя. Это можно сделать, например, через передачу префикса в GET/POST параметрах каждого запроса или через дополнительный куки.
Заключение
В заключение приведу полный конечный код наших функций для работы с сессиями PHP, включающий все рассмотренные выше задачи. function startSession($isUserActivity=true, $prefix=null) { $sessionLifetime = 300; $idLifetime = 60; if ( session_id() ) return true; session_name('MYPROJECT'.($prefix ? '_'.$prefix : '')); ini_set('session.cookie_lifetime', 0); if ( ! session_start() ) return false; $t = time(); if ( $sessionLifetime ) { if ( isset($_SESSION['lastactivity']) && $t-$_SESSION['lastactivity'] >= $sessionLifetime ) { destroySession(); return false; } else { if ( $isUserActivity ) $_SESSION['lastactivity'] = $t; } } if ( $idLifetime ) { if ( isset($_SESSION['starttime']) ) { if ( $t-$_SESSION['starttime'] >= $idLifetime ) { session_regenerate_id(true); $_SESSION['starttime'] = $t; } } else { $_SESSION['starttime'] = $t; } } return true; } function destroySession() { if ( session_id() ) { session_unset(); setcookie(session_name(), session_id(), time()-60*60*24); session_destroy(); } }

Надеюсь, эта статья сэкономит немного времени тем, кто никогда особо не углублялся в механизм сессий, и даст достаточно понимания этого механизма тем, кто только начинает знакомиться с PHP.

Теги:
  • php
  • сессии
  • cookie
  • аутентификация
  • идентификация
  • авторизация

Как использовать сессии и переменные сессий в PHP

Обработка сессии это ключевой приём в PHP, что позволяет хранить данные пользователя на всех страницах веб-сайта или приложения. Из этой статьи вы узнаете основы обработки сессии в PHP.

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

Что такое сессия в PHP?

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

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

Следующая диаграмма вкратце изображает протокол HTTP.

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

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

Обработка входа с сессиями и файлами «куки» (cookie)

Давайте быстро рассмотрим общий пример входа на веб-сайт, чтобы понять, что происходит за кулисами.

  1. Пользователь открывает страницу входа на веб-сайт.
  2. После отправки формы входа, сервер, на другом конце, аутентифицирует запрос, проверив введённые учётные данные.
  3. Если учётные данные, введённые пользователем, верны, сервер создаёт новый сеанс. Сервер генерирует уникальное случайное число, которое называется идентификатором сеанса. Также, на сервере, создаётся новый файл, который используется для хранения информации, относящейся к сеансу.
  4. Затем, идентификатор сеанса передаётся обратно пользователю, вместе с тем, что он запросил. За кулисами этот идентификатор сеанса отправляется в заголовке ответа «куки» PHPSESSID (так называется по умолчанию).
  5. Когда браузер получает ответ от сервера, он получает заголовок куки-файла PHPSESSID. Если в браузере разрешены «куки», то он сохранит этот PHPSESSID, в котором хранится идентификатор сеанса, переданный сервером.
  6. Для последующих запросов, «кука» PHPSESSID передаётся обратно на сервер. Когда сервер получает «куку» PHPSESSID, он пытается инициализировать сеанс с этим идентификатором сеанса.  Он делает это, загружая файл сеанса, который был создан ранее во время инициализации сеанса. Затем он инициализирует суперглобальную переменную массива $_SESSION с данными, хранящимися в файле сеанса.

Таким образом, пользовательские данные сохраняются даже в нескольких запросах, и пользователь не теряется на протяжении всего сеанса.

На следующей диаграмме показано, как протокол HTTP работает с сеансами.

Теперь, когда вы увидели краткое введение в работу сессий, мы создадим несколько практических примеров, чтобы продемонстрировать, как создавать и манипулировать переменными сессии.

Как запустить сессию

В этом разделе мы обсудим, как запустить сессию в PHP.

Всякий раз, когда вы хотите поработать с переменными сеанса, необходимо убедиться, что сеанс уже запущен. Сеанс в PHP можно запустить несколькими способами.

Использование функции session_start

Метод, в котором сессия запускается функцией session_start, вы будете видеть часто.

Важно, чтобы функция session_start вызывалась в начале скрипта, перед отправкой чего-либо браузеру. В противном случае, вы столкнётесь с печально известной ошибкой Headers are already sent.

Автоматический запуск сеанса

При необходимости применения сессий в приложении, есть возможность запускать сеанс автоматически без использования функции session_start.

В файле php.ini есть параметр session.auto_start, который позволяет запускать сеанс автоматически для каждого запроса. По умолчанию установлено значение 0 (выкл), и вы можете установить его на 1 (вкл), чтобы включить функцию автоматического запуска.

session.auto_start = 1

С другой стороны, если у вас нет доступа к файлу php.ini, и вы используете веб-сервер Apache, эту переменную можно задать с помощью файла .htaccess.

php_value session.auto_start 1

Если вы добавите строку выше в ваш .htaccess файл, то это должно автоматически запускать сессии в вашем PHP-приложении.

Как получить идентификатор сеанса

Как мы уже рассмотрели ранее, сервер создаёт уникальный номер для каждой новой сессии. Если вы хотите получить идентификатор сеанса, можно использовать функцию session_id, как показано в следующем фрагменте.

Это должно выдать вам идентификатор текущего сеанса. Функция идентификатора session_id интересна тем, что она ещё может принимать один аргумент — идентификатор сеанса.  Если вы хотите заменить сгенерированный системой идентификатор сеанса на ваш, это можно сделать, передав первый аргумент функции session_id.

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

Создание переменных сеанса

В этом разделе мы изучим, как инициализировать переменные сессии в PHP.

Как мы уже обсудили, при запуске сеанса, инициализируется суперглобальный массив $_SESSION с соответствующей информацией о сессии. По умолчанию, он инициализируется в виде пустого массива, и вы можете хранить больше информации, используя пару ключ–значение.

Давайте рассмотрим следующий пример кода, который показывает, как инициализировать переменные сеанса.

Как видите, мы запустили сессию в начале скрипта, используя функцию session_start. После этого мы инициализировали несколько переменных сессии. Наконец, мы использовали эти переменные через суперглобальную переменную $_SESSION.

При хранении данных сеанса с помощью $_SESSION, в итоге, они хранятся в соответствующем файле сессии на сервере, который был создан, когда сессия была запущена. Таким образом данные сеанса совместно используются несколькими запросами.

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

Как изменять и удалять переменные сеанса

Можно изменять или удалять переменные сеанса, созданные ранее в приложении так же, как обычные переменные PHP.

Давайте посмотрим, как изменять переменные сессии.

В приведённом выше коде, мы проверяем, установлена ли переменная $_SESSION['count']. Если не установлена, мы устанавливаем её равной 1, в противном случае, увеличим её на 1. Таким образом, если вы обновите эту страницу несколько раз, вы должны увидеть, что счётчик, каждый раз, увеличивается на единицу!

С другой стороны, если вы хотите удалить переменную сеанса, вы можете использовать функцию unset, как показано в следующем фрагменте.

Таким образом, вы больше не сможете обращаться к переменной $_SESSION ['logged_in_user_id'], поскольку она удалена функцией unset. Вот так вы можете изменить информацию о сеансе.

Как уничтожить сессию

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

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

Функция session_destroy удаляет всё, что хранится в текущем сеансе. Таким образом, с последующими запросами вы увидите пустую переменную $_SESSION, поскольку данные сеанса, хранящиеся на диске, были удалены функцией session_destroy.

Как правило, функцию session_destroy нужно использовать, когда пользователь выходит из системы.

Заключение

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

В первой половине статьи мы обсудили основные концепции сеансов, а затем мы создали несколько примеров на PHP, чтобы продемонстрировать, как вы могли создавать и уничтожать сеансы, а также манипулировать переменными сеанса.


Смотрите также



Компьютерные курсы по направлениям:

Для начинающих


A

Компьютер для начинающих: Word, Excel, Access и другие программы!

Графические пакеты


B

Популярные пакеты Adobe Photoshop, CorelDraw, ArchiCAD, AutoCAD и другие!

WEB + анимация


C

Курсы по созданию сайтов, WEB-дизайну и крутой анимации в Adobe Flash!

Бухгалтерия + делопроизводство

Сетевые технологии


E

Курсы сборки ПК, системных администраторов и защиты информации!