Как узнать, активен ли сеанс?
В запросе есть несколько разных способов определить, был ли запущен сеанс, например:
$isSessionActive = (session_id() != "");
Или:
$isSessionActive = defined('SID');
Однако, оба они не работают, если вы начинаете сеанс, а затем закрываете его; session_id()
вернет прежний идентификатор сеанса, а SID
будет определен. Аналогично, вызов session_start()
в этот момент будет генерировать E_NOTICE
, если у вас уже есть сеанс. Есть ли разумный способ проверить, активен ли сеанс в настоящий момент, не прибегая к буферизации вывода, оператору запирания (@session_start()
) или чему-то еще в равной степени хакерским?
EDIT: я написал патч, чтобы попытаться включить эту функциональность в PHP: http://bugs.php.net/bug.php?id=52982
EDIT 8/29/2011: новая функция добавлена в PHP 5.4, чтобы исправить это: "Открыть статус сеанса с помощью новой функции session_status"
// as of 8/29/2011
$isSessionActive = (session_status() == PHP_SESSION_ACTIVE);
EDIT 12/5/11: session_status() в руководстве по PHP.
Ответы
Ответ 1
См. редактирование исходного вопроса; в основном, PHP 5.4 и выше теперь имеет функцию session_status()
, чтобы решить эту проблему!
"Открыть статус сеанса с помощью новой функции session_status" (версия SVN 315745)
Если вам нужна эта функциональность в версии до версии PHP 5.4, см. ответ hakre.
Ответ 2
Я работал над этим, добавляя пару функций-оболочек вокруг различных функций создания/закрытия сеанса/уничтожения. В основном:
function open_session() {
session_start();
$_SESSION['is_open'] = TRUE;
}
function close_session() {
session_write_close();
$_SESSION['is_open'] = FALSE;
}
function destroy_session() {
session_destroy();
$_SESSION['is_open'] = FALSE;
}
function session_is_open() {
return($_SESSION['is_open']);
}
Hackish, но выполнил то, что мне нужно.
Ответ 3
Я тоже сталкиваюсь с этим, и настройка в $_SESSION
для меня не является вариантом. Для PHP 5.3.8:
- Если какой-либо сеанс запущен с запросом,
define('SID')
вернет FALSE
, а также $_SESSION
не будет установлен.
- Это не зависит от того, используется ли
session_id()
для установки идентификатора сеанса или нет.
- После определения первого
session_start()
, SID
и $_SESSION
установлен пустой массив.
-
session_destroy()
отключает session_id()
, тогда это пустая строка. SID
будет оставаться определенным (и установить для него предыдущее значение, которое может быть пустой строкой). $_SESSION
остается неизменным. Он получит reset/заселен в следующий раз session_start
.
С этими состояниями, особенно в качестве session_id()
можно вызвать между ними, чтобы установить идентификатор для следующего сеанса, невозможно безопасно определить состояние сеанса с помощью SID
, $_SESSION
и session_id()
.
"Попытка" с помощью session_start()
(например, с @
) может оказаться не очень полезной, так как это изменит статус сеанса и изменит содержимое $_SESSION
(и добавит заголовок set-cookie, если файл cookie был а не часть запроса). Это было неуместно в моем случае.
Пока я запускал тесты, я сталкивался с этим поведением, что вы не можете попытаться изменить настройку ini session.serialize_handler
, когда сеанс активен, даже если вы установите его на одно и то же значение. То же самое верно для session.use_trans_sid
Docs, который является более легким. Это привело меня к следующей функции:
/**
* @return bool
*/
function session_is_active()
{
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$result = @ini_set($setting, $current);
return $result !== $current;
}
Насколько я вижу, ошибка проверяет только активный статус сеанса (не отключен), поэтому это не должно возвращать ложный положительный результат при отключении сеансов.
Чтобы эта функция была совместима с PHP 5.2, она нуждается в небольшой модификации:
/**
* @return bool
*/
function session_is_active()
{
$setting = 'session.use_trans_sid';
$current = ini_get($setting);
if (FALSE === $current)
{
throw new UnexpectedValueException(sprintf('Setting %s does not exists.', $setting));
}
$testate = "mix$current$current";
$old = @ini_set($setting, $testate);
$peek = @ini_set($setting, $current);
$result = $peek === $current || $peek === FALSE;
return $result;
}
Некоторая песочница.
Ответ 4
Следующий код только сбрасывает один session_id() для меня, а не два
session_start();
echo session_id();
session_destroy();
echo session_id();
Если у вас возникают трудности с этим, вы можете попробовать создать переменную для проверки, которую вы уничтожаете, когда вы уничтожаете сеанс.
session_start();
$_SESSION['intialized'] = 'This will not print';
$_SESSION = array(); // Unset all variables
session_destroy();
echo $_SESSION['initialized']; // No output
Ответ 5
Здесь хорошее падение в замене, которое не сломается, когда вы перейдете к 5.4:
if(!function_exists('session_status')){
function session_active(){
return defined('SID');
}
}else{
function session_active(){
return (session_status() == PHP_SESSION_ACTIVE);
}
}
Ответ 6
Кен, если сеанс уничтожен, массив $_SESSION не должен быть доступен... или, по крайней мере, ваши значения должны быть отменены. Итак, в теории (untested) вы должны иметь возможность проверить массив на значение, чтобы знать, установлено ли что-либо в данный момент.
Ответ 7
Существует несколько мест, которые необходимо проверить, чтобы проверить, что сеанс активен:
1 cookie существует и не истек
2-й механизм хранения основной сессии (файловая система или база данных) имеет запись, соответствующую файлу cookie.