Постоянный вход с Zend_Session:: rememberMe

Я использую Zend_Session для управления моими пользовательскими сеансами, и я пытался реализовать опцию "Запомнить меня" в моем приложении, чтобы пользователи не вошли в систему в течение 2 недель или около того.

Я заметил, что Zend_Session уже имеет встроенную функцию под названием Zend_Session::rememberMe, однако я не уверен, правильна ли эта логика функций для использования в качестве сохраненного входа.

По сути, функция rememberMe просто увеличивает срок действия активного сеанса, что означает, что если пользователь использует опцию "запомнить меня", он будет оставаться включенным в течение 2 недель с активной сессией.

Это вызывает две основные проблемы.

  • Я храню сеансы в базе данных, что означает, что все эти неактивные пользователи хранятся в течение 2 недель в моей таблице сеансов. У меня более 50 тыс. Неактивных сессий, и это вредит производительности приложения.
  • Я хочу узнать, вернулся ли пользователь на сайт после 24 часов бездействия и повторно подтвердил свою информацию. Поскольку его сеанс остается открытым, я не могу сказать, вернулся ли он через 1 час или 1 неделю, так как он имеет тот же самый активный идентификатор сеанса.

Я читал, что если я хочу реализовать функцию "запомнить меня", я не должен использовать для этого cookie сеанса, и я должен создать еще один "cookie для входа", чтобы запомнить хешированный user_id и токен. здесь полное объяснение: Каков наилучший способ реализации "запомнить меня" для веб-сайта?

Итак, почему платформа zend предлагает такую ​​функцию, если ее использование может создать проблемы с производительностью и безопасностью?

Ответ 1

+1, отметив главный недостаток подхода Zend к функциональности "запомнить меня". Некоторые люди не понимают, что существует наказание, когда они пытаются продлить время жизни сеанса, независимо от того, какой обработчик сеанса является файлом или db. Разрешение устаревших сеансов сохраняется за разумные временные рамки - это слабое решение, и вам лучше реализовать настраиваемое решение cookie, описанное в приведенной ссылке.

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

Кроме того, если вы хотите отслеживать, вернулся ли пользователь и восстановил устаревший сеанс, вы можете добавить столбец "updated_at" в таблицу отслеживания сеансов. Итак, у вас будет две столбца временной метки; created_at и updated_at, что поможет вам сделать это определение.

Ответ 2

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

Конечно, могут быть непредвиденные последствия, если кто-то произвольно устанавливает его в очень большое значение, но следует отметить, что данные сеанса по-прежнему подлежат сборке мусора на основе session.gc_maxlifetime, независимо от времени rememberMe, установленного в файле cookie. Вызов Zend_Session::rememberMe() не влияет на сбор мусора для этих данных.

Рассмотрим следующее:

Bootstrap.php

protected function __initSession() {
    ini_set('session.gc_maxlifetime', 45);  // set session max lifetime to 45 seconds
    ini_set('session.gc_divisor', 1);       // 100% chance of running GC
    Zend_Session::start();
}

IndexController.php

public function indexAction() {
    $data = new Zend_Session_Namespace('data');

    if (!isset($data->time)) {
        // no active session - set cookie lifetime and set some data
        Zend_Session::rememberMe(90*86400);  // 90 days
        $data->time = time();
        echo "Setting time";
    } else {
        echo date('r', $data->time);
    }
}

Если вы получили доступ к IndexController, первый раз вы увидите Setting time. Затем, если вам нужно подождать более 45 секунд, вы увидите распечатанное время и (в моем случае) по следующему запросу, срок действия которого истек. Данные сеанса удаляются с сервера, и хотя у меня все еще есть предыдущий файл cookie, он больше не распознается сервером.

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

Чтобы ответить на ваши 2 вопроса:

Что касается вашей первой проблемы, я бы поставил под вопрос, почему 50 000 неактивных сеансов ухудшают производительность. Если база данных должным образом проиндексирована в идентификаторе сеанса, она должна быть чрезвычайно быстрой для получения данных сеанса, даже если в базе данных было миллионы сеансов. Возможно, вы попали в аппаратное ограничение? При правильном выборе данных из 50 000 записей должно быть немного накладных расходов.

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

По соображениям безопасности, если вы обнаружите, что это было так долго с момента их последнего посещения, это подходящее время для повторного вызова rememberMe(), так как это приведет к выпуску нового файла cookie и предотвратит захват и фиксацию сеанса.