Сегодня я заметил что-то тревожное, проверяя файлы сеанса в папке storage/framework/sessions
, созданной Laravel 5.
Вот что произошло:
- Я вошел как пользователь A
- Я перешел на страницу, в которой хранится переменная X в сеансе
- Я вышел из системы, но не закрыл браузер.
- Файл сеанса в
storage/framework/sessions
был все еще там, и браузер печенье было живым. - Я вошел в систему как пользователь B.
- Старый файл сеанса в
storage/framework/sessions
удален и появился новый файл сеанса. - Я просмотрел новый файл сеанса - удивление! переменная X выжила и все еще существует, доступна для пользователя B!
Это приводит к проблемам безопасности, поскольку теперь пользователь B имеет доступ к данным пользователя A.
Во время отладки через исходный код Laravel я обнаружил, что Session Store никогда не очищается во время процесса выхода из системы/входа в систему. Только учетные данные для входа удаляются в методе Illuminate\Auth\Guard::clearUserDataFromStorage()
, но все атрибуты Store Store все еще существуют, а затем позже, когда вызывается $kernel->terminate($request, $response);
, что в свою очередь приводит к Illuminate\Session\Middleware\StartSession::terminate()
вызову Store::save()
, который вслепую сохраняет $this->attributes
к новому сеансу, игнорируя тот факт, что он теперь принадлежит другому пользователю.
С одной стороны, это кажется логичным - у Laravel нет никаких предположений относительно моих данных, и я хочу, чтобы он истекал вместе с аутентификацией или нет. Но было бы замечательно, если бы он где-то документировал решение для прикрепления некоторых конфиденциальных данных к объекту аутентификации и истечения срока его действия вместе с ним.
Это означает, что я как программист отвечаю за полное удаление всех конфиденциальных данных из текущего сеанса, когда новый (или тот же) пользователь входит в систему.
Очистка при выходе из системы не будет надежной, потому что пользователь никогда не сможет нажать ссылку "Выход", но дождитесь окончания срока действия сеанса, что для Laravel все еще не очищает сеанс.
Еще одна вещь, о которой нужно помнить: я не должен очищать сессию слишком рано - есть токен AntiForgery, который должен присутствовать, иначе форма входа всегда терпит неудачу.
Я нашел тему форума, которая также пытается решить несколько схожую проблему:
http://laravel.io/forum/04-27-2014-how-to-expire-session-data
Я смутился этим:
У меня был еще один вопрос на этом сегодня и понял, в чем проблема: Session:: flush() не удаляет данные сеанса, которые создает приложение, например данные корзины покупок
Если это так, то единственный способ полностью избавиться от сеанса - использовать PHP native session_unset()
и session_destroy()
, но я бы не хотел идти таким путем - я бы предпочел найти чище, Решение Laravel-ish, если возможно.
Как сообщить Laravel, что я хочу, чтобы мои старые данные сеанса удалялись вместе с данными аутентификации пользователя, когда истекает срок аутентификации или пользователь выходит из системы?