Переменные сессии исчезают для некоторых пользователей (drupal) - PullRequest
2 голосов
/ 02 апреля 2012

У меня есть проблема на моем сайте, которая преследует меня месяцами.Я продолжаю обходить его, но теперь мне кажется, что я не могу найти такой способ, поэтому я решил, почему бы не решить корневую проблему?

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

Я использую drupal 6.

Есть предложения?

Ответы [ 7 ]

4 голосов
/ 12 апреля 2012

Несколько вещей, которые вы можете проверить

  1. Как настроен ваш сеансовый сборщик мусора?Пожалуйста, проверьте настройки PHP: session.gc_maxlifetime, session.gc_divisor, session.session.gc_probability.Это только предположение, но, возможно, GC удаляет ваши данные.
  2. Исчезают ли данные из таблицы сеансов?Если вы используете обработчик сеансов по умолчанию для Drupal, данные таблицы $ _SESSION сохраняются в столбце сеансов таблицы сеансов в сериализованной форме.
  3. Если данные исчезают из базы данных и если вы можете повторить проблему на своем сервере разработки, вы также можете включить ведение журнала запросов для вашей базы данных (в конфигурации сервера mysql см. http://dev.mysql.com/doc/refman/5.1/en/query-log.html для более подробной информации).С включенным модулем devel вы можете декорировать (настройки модуля devel) свои запросы комментариями, включая информацию о функции, выполняющей запрос.Это может помочь вам найти проблему. НЕ ПЫТАЙТЕСЬ НА производственную среду
  4. Иногда проблема может быть вызвана одним из включенных модулей, который наносит вред вашей таблице $ _SESSION.Попробуйте найти все вхождения $ _SESSION в коде ваших включенных модулей, особенно в контексте записи.Некоторое регулярное выражение поможет в этой задаче.
0 голосов
/ 02 апреля 2019

Я отслеживаю этот пост, потому что, похоже, ни один из ответов не решил проблему. У меня была похожая проблема в D7 (и mod_fcgi), и поэтому я нашел этот поток, эффект не ограничен Drupal 6, служба временного хранения в Drupal 8 может облегчить это.

Короче говоря, я бы рассматривал состояние расы как основную причину. Веб-сайты, созданные с использованием Drupal и других фреймворков, использующих Ajax, могут стать сложными зверями с одновременным доступом к переменным сеанса. Сначала я бы посмотрел на длительные запросы, используя, например, Firefox-Developer Edition, анализатор трафика и т. д. Такие могут быть представлены, например, в блоках или другой структуре на сайте, любой из которых может получить доступ к $ _SESSION. Затем отключите как можно больше блоков и меню, пока проблема не исчезнет.

Кроме того, вы можете добавить отладочную информацию к includes/session.inc в функциях drupal_session_start() и drupal_session_commit(). Выходные данные должны содержать идентификаторы процессов сервера. Ищите коммиты, которые происходят спустя много времени после отображения основного контента.

Гипотеза о том, что может происходить

Длительный запрос перезаписывает переменные сеанса со старым состоянием. Отчасти это связано с тем, как переменные сеанса управляются в Drupal. По умолчанию данные сеанса хранятся в столбце сеанса таблицы сеансов в виде единого сериализованного строкового представления данных. В принципе, чтение и запись переменных сеанса должно быть атомарным действием, но это не так легко осуществить. Код ниже взят из файла session.inc и обрабатывает запись данных сеанса. Он использует метку времени и флаг is_changed для эффективной задержки записи. Можно также сказать, что сессии не являются потокобезопасными. Кроме того, он использует операторы SQL MERGE, но не может объединять сериализованные переменные; по сути, последнее написанное состояние - это состояние победы.

    // For performance reasons, do not update the sessions table, unless
    // $_SESSION has changed or more than 180 has passed since the last update.
    if ($is_changed || !isset($user->timestamp) || REQUEST_TIME - $user->timestamp > variable_get('session_write_interval', 180)) {
      // Either ssid or sid or both will be added from $key below.
      $fields = array(
        'uid' => $user->uid,
        'cache' => isset($user->cache) ? $user->cache : 0,
        'hostname' => ip_address(),
        'session' => $value,
        'timestamp' => REQUEST_TIME,
      );

    ...

    db_merge('sessions')
    ->key($key)
    ->fields($fields)
    ->execute();

Представьте себе следующий сценарий:

Основным содержанием сайта является модуль, который отображает кнопку и счетчик. Счетчик сохраняется в $ _SESSION ['counter'] и увеличивается с помощью нажатия кнопки. Кнопка имеет обратный вызов Ajax, который эффективно выполняет следующее

function counter_increment(){
   if (!drupal_session_started()) {
        // Must initialize sessions for anonymous users.
        drupal_session_start();
   }
   $_SESSION['counter'] = (isset($_SESSION['counter'])) ? $_SESSION['counter']++ : 0;
   drupal_session_commit();
   ...
}   

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

function do_nothing(){
   if (!drupal_session_started()) {
        // Must initialize sessions for anonymous users.
        drupal_session_start();
   }
   $otherdata = $_SESSION['otherdata'];
   // do something that takes a long time and eventually is finished or fails, like starting a site search:
  wait(200); // might work, request is now older than write delay (default 180)
  $_SESSION['otherdata'] = $otherdata; // session is updated now, too, possibly not necessary
  return TRUE;
 }   

Таким образом, как только содержимое загружено, блок нижнего колонтитула вызывает do_nothing, которое зависает в течение> 180 секунд. Тем временем пользователь увеличивает счетчик с помощью обратного вызова, но после завершения do_nothing все содержимое сеанса будет заменено содержимым сеанса запроса do_nothing, что приведет к потере $ _SESSION ['counter'];

0 голосов
/ 17 апреля 2012

Я слышал о проблеме session_regenerate_id () в Drupal с какой-то конкретной версией PHP. Не могли бы вы попытаться отключить эту функцию и проверить ее?

0 голосов
/ 17 апреля 2012

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

Доступ к сайту был разрешен как через www.example.com, так и на example.com, что работало до тех пор, пока пользователь не нажал ссылку, которая была жестко закодирована с именем домена oposit. Затем он переключил домен / поддомен и apache / php создал новый сеанс для пользователя в «новом» домене. Это было особенно неприятно, когда люди возвращались с оплаты.

В нашем случае решением было заставить пользователей всегда использовать только example.com и либо отключить, либо перенаправить все запросы на www.example.com напрямую на example.com. Таким образом, вы никогда не получите сессий на обоих.

0 голосов
/ 16 апреля 2012

Я думаю, что ваша проблема с сессионным путем сохранения

Пожалуйста, создайте папку с именем (chmod 777 MUST) в вашей корневой директории, т.е. где находится .php, и поместите этот код

if(!is_writable(session_save_path())){
    session_save_path(dirname(__FILE__)."/<xyz>");
}

Перед началом сеанса.

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

0 голосов
/ 12 апреля 2012

Я думаю, здесь немного, но я думаю, что это может быть вашей проблемой / решением:

Краткий ответ: попробуйте установить для session.cookie_lifetime в sites / default / settings.php значение 0.

Длинный ответ: сеанс зависит от данных сеанса на сервере и cookie сеанса PHP на клиенте. Если вы установите слишком низкое время жизни файла cookie сеанса (по умолчанию Drupal составляет 23 дня, поэтому обычно это не проблема), сеанс может быть эффективно «уничтожен» на стороне клиента (браузер удаляет файл cookie, поскольку срок его действия истек).

Однажды я столкнулся с этой проблемой, потому что я изменил время жизни файлов cookie сеанса Drupal с 23 дней до чего-то меньшего, что казалось более «подходящим» в попытке ограничить продолжительность входа в систему из соображений безопасности. Но уменьшение времени жизни файла cookie сеанса не является решением. Лучший способ сделать это - ограничить продолжительность сеанса на стороне сервера. Вы можете сделать это, установив session.gc_maxlifetime (также в настройках Drupal) на что-то вроде 7200 (на 2 часа). Затем вам нужно только убедиться, что сборка мусора сеанса выполняется достаточно часто, чтобы сеансы надежно заканчивались через 2 часа.

Затем, чтобы избежать проблем с уничтожением файлов cookie на стороне клиента, вы можете установить для session.cookie_lifetime значение 0. Это гарантирует, что, пока пользователь находится на сайте, он будет выходить из системы, только если он останется неактивен дольше, чем session.gc_maxlifetime. И вдобавок ко всему, он также ВЫХОДИТ ИЗ ПОЛЬЗОВАТЕЛЯ, когда он ЗАКРЫВАЕТ БРАУЗЕР. Что не сделано Drupal по умолчанию !!

СУЩЕСТВЕННОЕ ОБНОВЛЕНИЕ: почему рекомендуется установить время жизни файлов cookie равным 0? Потому что в противном случае СЕРВЕР устанавливает ДАТУ / ВРЕМЯ, в которые клиенту нужно ОБНОВИТЬ cookie. Так что, вы могли бы сказать? Хорошо, рассмотрим следующую ситуацию: если у КЛИЕНТА ЕГО ЧАСЫ НАСТРОЕНЫ НЕПРАВИЛЬНО (да, это происходит, даже если большинство компьютеров обновляют свое время через NTP, а некоторые нет) !! Срок действия файла cookie может истечь намного раньше, чем вы думаете, ДАЖЕ ПО ПРИБЫТИИ. Это была именно та проблема, которую мне пришлось отладить однажды ...

Так что попробуйте время жизни куки 0 как минимум ОДИН РАЗ, если у вас возникнут странные проблемы с сессией:)

0 голосов
/ 02 апреля 2012

Добавьте ob_start() и session_start(); вверху вашего скрипта.

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