PHP: как не потерять сессию
Достаточно часто встречается ситуация, когда авторизованный пользователь уходит из-за компьютера или просто переключается на какую-либо другую задачу, забывая при этом периодически покликивать по ссылкам сайта. Результат: по возвращении к работе с сайтом после первого же клика его нагло выбрасывает из теплой и уютной админки с нахальным требованием залогиниться заново.
Во время разработки моего последнего проекта подобные ситуации с пользователями также происходили. Согласен, обидно, когда набираемый и корректируемый в течение получаса текст вдруг уходит в небытие и никакими силами его уже не спасти. Решив раз и навсегда покончить с этой проблемой (в конце-то концов сайты делаются, собственно, для их посетителей), я набросал несколько строк кода. И — о чудо! — проблема решилась.
Прочему происходит разрыв сессии
Здесь все просто. Сессия рвется потому, что веб-сервер старается держать только сессии активных пользователей. Активными, по его мнению, считаются те, которое запрашивают у него новые страницы не реже, чем… указано в настройках сервера. Как правило, эта настройка записывается там, куда не имеет доступа даже арендатор сервера.
Можно, конечно, забрасывать письмами админов хостера с требованием увеличить время сессии, а то и сделать ее бесконечной, но мало кто на это пойдет. Подвергать такому риску свои сервера хостер будет только в том случае, если Вы неслабо платите за его услуги. Если же у Вас простой виртуальный хостинг — на положительный ответ можете даже не надеяться. Значит, пойдем другим путем.
Как поддержать сессию автоматически
Теперь, когда мы знаем, что для поддержания сессии нужно всего лишь периодически запрашивать у сервера какие-нибудь данные, решение напрашивается само собой. Нужно просто запрашивать эти самые данные. Это можно делать вручную, кликая по каким-нибудь ссылкам в новых вкладках браузера, в этом случае сессия будет поддерживаться и в той вкладке, где тихо и меланхолично набирается какой-нибудь текст в WYSIWYG-редакторе. Но попробуйте-ка все это растолковать пользователю, который кроме браузера ничего особо и не знает. Он решит, что Вы хотите над ним просто поиздеваться, отправит Вас без снаряжения в пешее эротическое и забьет на Ваш ресурс. И правильно, кстати, сделает! Нехорошо в наши дни заставлять пользователя заниматься таким грязным делом.
Но идея-то с поддержкой сессий таким вот образом — хороша! Настолько хороша, что от нее совершенно не хочется отказываться. А мы отказываться от нее и не будем. Отправлять запросы серверу браузер будет самостоятельно, без какого-либо пользовательского участия. Он просто будет информировать сервер, мол, эй, я живой, не рви мою сессию и сервер его прекрасно поймет. Это чем-то похоже на команду ping, когда клиент просто сообщает о своем присутствии — и ничего больше. Потому этот скрипт я так и решил обозвать — пингер.
Пингер: клиентская сторона
Повторюсь. Для того, чтобы сервер не рвал сессию пользователя, нам нужно периодически запрашивать у сервера какие-либо данные. Желательно, как можно меньших объемов, поскольку эти самые данные нам не нужны. Нам нужно лишь «отметиться» на сервере. Поэтому воспользуемся обычным post-запросом с помощью jQuery:
$(document).ready(function() { var result = ''; setInterval(pinger, 300000); }); function pinger() { $.post("/ajax/pinger.php", function(result) { }); }
После создания HTML-документа у нас запустится код, заключенный в $(document).ready()
. А это значит, что каждые 5 минут (5 x 60 x 1000 = 300000 миллисекунд) будет выполняться функция pinger()
, в которой и размещается наш post-запрос. Давайте немного разберем, что и как он делает.
.post( url, [data], [callback], [type] )
Первый (обязательный) параметр — это URL страницы, к которой мы обращаемся. Ее код я дам чуть позже. Второй — данные, передаваемые скрипту на сервер. Третий — функция, которая выполнится после выполнения запроса (нам оно сейчас не надо). И, наконец, четвертый — тип передаваемых данных (XML, JSON, HTML etc). Функцию во втором параметре я оставил на всякий случай — скорее всего мне на боевом проекте понадобится не только «пинговать».
Пингер: серверная сторона
Ну а здесь совсем просто. Запускаем сессию, выводим что-нибудь, чтобы не отдавать пустой документ:
session_start(); echo 'ok'; session_write_close();
Не пугайтесь, уважаемый читатель. Последней инструкцией мы ни в коем случае не убиваем сессию. Мы всего лишь навсего открываем к ней доступ для других скриптов. Вся наша сессия, все данные в ней успешно остаются храниться в ней же. А вот «свежесть» сессии успешно обновляется, что нам, собственно, и нужно.
Результат работы пингера
Результатом работы этого пингера стало отсутствие жалоб от пользователей на «вылетание» админки сайта. А это куча сэкономленных нервов и времени на разъяснения, почему такое происходит. Работает — и работает, пользователь даже не замечает этого. Чего, собственно, я и добивался.