ZF2: как реализовать тайм-аут сеанса и исправить фиксацию сеанса
Я хочу, чтобы мои сеансы истекали после 30 минут бездействия, однако, когда я настраивал это, мои пользователи выходили из системы случайным образом, даже если у них могло быть только несколько секунд бездействия. Я думаю, что проблема заключается в восстановлении идентификатора сессии.
Насколько я понимаю, чтобы получить желаемый эффект, мне нужно настроить Remember_me_seconds в моем сеансе на 1800. Затем в моем загрузчике после вызова $sessionMgr->start()
Мне нужно позвонить $sessionMgr->rememberMe()
,
rememberMe()
звонки regenerateId()
И я думаю, что именно в этом проблемы. Я думаю, что если браузер быстро запускает два запроса, первый запрос обрабатывается, а идентификатор сеанса обновляется на сервере. Когда второй запрос получен сервером, он все еще несет старый идентификатор сеанса, который больше не распознается, поэтому сервер обрабатывает вас так, как будто вы вышли из системы. Возможно ли это звучит? Я думаю, что это должно быть, так как я могу смоделировать проблему, позвонив regenerateId()
напрямую (вместо звонка rememberMe()
)
Итак, вопрос в том, как мне реализовать желаемое решение? Что касается времени ожидания сеанса, я могу сохранить время последнего доступа в моем сеансе и сравнивать его с текущим временем при получении запроса. Но это сделало бы rememberMe()
функциональность избыточна. А что касается регенерации идентификатора, чтобы избежать фиксации сеанса, я не вижу, как я мог бы сделать это эффективно. Всегда будут ситуации, когда есть несколько запросов браузера в быстрой последовательности, поэтому вероятность того, что сервер будет не синхронизирован...
2 ответа
ОК, я подхожу к этому не с того угла. Я предполагал, что "запомнить меня" и "время жизни куки" были разработаны, чтобы помочь с тайм-аутом сеанса. Как ясно из этого вопроса, как мне закончить сеанс PHP через 30 минут? Я должен реализовать свое собственное решение.
Кроме того, после прочтения этой статьи, http://phpsec.org/projects/guide/4.html, я вижу, что мне действительно нужно заново генерировать идентификатор сеанса только тогда, когда пользователь входит в систему или выходит из нее.
Для тайм-аута сессии вы можете сделать следующее. У меня есть это в классе, который расширяет каждый контроллер, и этот метод тайм-аута запускается при каждом запросе. Кроме того, значение времени ожидания изначально устанавливается при входе в систему.
/**
* If user is inactive for 5 minutes, log them out.
*
* @return void | Zend\Mvc\Controller\Plugin\Redirect
*/
protected function timeout()
{
// User Active so reset time session. (5minutes)
// Note: (I'm using $this->identity which is basically an Auth object)
// but would work the same way as $_SESSION['timeout']
if ($this->identity->timeout + 300 > time())
{
$this->identity->timeout = time();
}
// session timed out, logout user
// this routes to the location of destroying the session, etc.
else
{
return $this->redirect()->toRoute('logout', array());
}
}
Кроме того, если вы хотите автоматически выйти из системы без необходимости обновлять страницу, вы, вероятно, захотите использовать AJAX для проверки значения времени ожидания через (n) секунд для сброса.
Предотвращение фиксации сессии: я еще не реализовал это в ZF2. Однако я сделал в ZF1, и он работал без проблем. Я знаю, что на самом деле не дает ответа, но я предполагаю, что что-то в том же духе будет работать и в ZF2.
Случайный выход из системы: я видел в некоторых приложениях, где это было исправлено путем изменения некоторых свойств сеанса в файле php.ini. В другом приложении я сейчас использую ZF2 rememberMe($time)
без проблем.
Также может быть полезно посмотреть, как вы устанавливаете параметры хранения сеанса и инициализируете объект пространства имен сеанса. В Zend\Session\Container
обратите внимание на блок документа, который гласит:
/**
* Session storage container
*
* Allows for interacting with session storage in isolated containers, which
* may have their own expiries, or even expiries per key in the container.
* Additionally, expiries may be absolute TTLs or measured in "hops", which
* are based on how many times the key or container were accessed.
*/
Так что-то вроде этого:
$this->session = new SessionContainer($this->namespace, $manager);
И настройку запомнить меня:
$this->session->getManager()->rememberMe($time);
Надеюсь, это указывает на правильное направление.