2010-09-24 2 views
40

По желанию, есть несколько различных способов, которыми вы можете сказать, работает ли или нет сессии, такие как:Как узнать, активен ли сеанс?

$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, чтобы исправить это: "Expose session status via new function, session_status"

// as of 8/29/2011 
$isSessionActive = (session_status() == PHP_SESSION_ACTIVE); 

EDIT 12/5/11: session_status() в руководстве по PHP.

+0

Возможно, это хакеры: ['session_is_active()'] (http://stackoverflow.com/questions/3788369/how-to-tell-if-a-session-is-active/7656468#7656468), но по крайней мере, что-то я нашел. Спасибо за сообщение об ошибке в любом случае, приятно видеть это в 5.4. – hakre

+0

Все еще актуальный вопрос с добавлением 5.4, поскольку я только что нажал на поле 5.3 и нашел 'session_status()' missing! – quickshiftin

+0

Это, безусловно, странно, поскольку оно действительно присутствует на моей сборке 5.4. Areyou говорит, что вы используете 5.3 или 5.4? Является ли это обычным или предварительно созданным двоичным кодом PHP? В 'phpinfo()', есть ли у вас раздел «сеанс»? В действии: http://codepad.viper-7.com/PiZmcw – ken

ответ

3

Следующий код сбрасывает только одну 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 
+3

Но если вы используете session_write_close(), закрытые закрытые, но $ _SESSION данные сессии все еще существуют, и это то, что я думаю, что OP становится ... как вы проверяете, действительно ли сам файл сеанса используется? –

+0

Да, вы в основном разместили то же самое решение, что и я, установив переменную до ее закрытия (в любом случае) и проверив эту переменную ... – Robert

+0

Что сказал Марк Б. – ken

0

Кен, если сессия уничтожается, массив $ _SESSION не должен быть доступен ... или, по крайней мере, ваши ценности должны быть сняты с охраной. Итак, в теории (untested) вы должны иметь возможность проверить массив на значение, чтобы знать, установлено ли что-либо в данный момент.

+1

'session_destroy()' nor 'session_write_close()' unset '$ _SESSION'. – hakre

15

Я работал над этим, добавляя пару функций обертки вокруг различных функций создания сеанса/закрытия/уничтожения. В принципе:

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, но выполнил то, что мне было нужно.

+0

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

+0

в функции session_close есть блуждающая фигурная скобка, которая должна быть точкой с запятой. SO не позволит мне редактировать, потому что недостаточно символов для редактирования. :/ – ShadeTreeDeveloper

10

Я тоже сталкиваюсь с этим, и настройка в $_SESSION для меня не является вариантом. Для PHP 5.3.8:

  1. Если какой-либо сеанс был запущен с просьбой, define('SID') вернется FALSE, а также $_SESSION снята с охраны.
  2. Это не зависит от того, использовался ли session_id() идентификатор сеанса или нет.
  3. После первого session_start() определено значение SID, а $_SESSION - пустой массив.
  4. session_destroy() делает отмену session_id(), это пустая строка. SID будет оставаться определенным (и установить его прежнее значение, которое может быть пустой строкой). $_SESSION остается без изменений. Он будет сброшен/заселен в следующий раз, когда вызывается session_start.

С этими состояниями, особенно session_id() можно назвать между ними, чтобы установить идентификатор для следующей сессии , это не представляется возможным надежно определить состояние сеанса с SID, $_SESSION и session_id().

«Попытка» с session_start() (например, с @) не может быть очень полезно, так как это изменит состояние сеанса и изменения содержимого $_SESSION (и добавление заголовка Set-Cookie, если куки не является частью запроса). В моем случае это было неуместно.

Когда я выполнял тесты, я столкнулся с поведением, что вы не можете изменить настройку ini session.serialize_handler, когда сеанс активен, даже если вы установите его на то же значение. То же самое верно для session.use_trans_sidDocs, который является более легким. Это привело меня к следующей функции:

/** 
* @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; 
} 

Некоторые sandbox.

+1

Хотя это все еще несколько «взломанно», я впечатлен вашей техникой. Я думал, что есть некоторые признаки проблемы, которые могли бы окунуться (например, что вы здесь делаете), я просто не смог их найти. Очень хорошо! – ken

+0

Также есть песочница вашего сайта? Анализ опкода сладок. – ken

+0

Нет, это не мой сайт, но мне он тоже нравится. :) Прямо сейчас я не уверен в этом взломе, если он работает для PHP 5.1 (мне это может понадобиться). – hakre

1

Вот хороший падение замены, что не сломается вещи при переходе на 5.4:

if(!function_exists('session_status')){ 
    function session_active(){ 
     return defined('SID'); 
    } 
}else{ 
    function session_active(){ 
     return (session_status() == PHP_SESSION_ACTIVE); 
    }   
} 
+0

Как я уже говорил в своем первоначальном вопросе, это неадекватное решение; если вы вызываете 'session_start()', а затем вызываете 'session_write_close()', тогда 'defined (" SID ") === true', хотя сеанс не открыт. Такая методика может определить только, был ли сеанс запущен в течение цикла запроса, а не то, открыто или нет. Он может работать для некоторых прецедентов, но это не замена 'session_status()'. – ken

0

Есть несколько мест, которые необходимо проверить, чтобы проверить сеанс активен:

1- cookie существует и не истек . 2-х основанный механизм хранения сессии (файловая система или база данных) имеет запись, соответствующую файлу cookie.

+0

Я думаю, вы неправильно поняли цель/намерение. – ken

+0

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

+0

Следует избегать 'Примечание: сеанс уже запущен - игнорирование session_start()'. Эта ошибка содержит больше информации о прецеденте: http://bugs.php.net/bug.php?id=52982 – ken

Смежные вопросы