У меня есть приложение Symfony 3.2, которое предоставляет REST API и использует Json Web Tokens (JWT) для аутентификации. Недавно я перешел на использование компонента Symfony’s Guard. Теперь мой security.yml
содержит следующий раздел конфигурации брандмауэра (я использую пакет Lexik JWT 2.4.0, но это не имеет значения):
firewalls:
# ...
api:
pattern: ^/api
stateless: true
guard:
authenticators:
- lexik_jwt_authentication.jwt_token_authenticator
Поскольку я сделал это переключение, я заметил, что каждый запрос обрабатывается так, как если бы пользователь только что вошел в систему, т.е. запускается событие security.interactive_login
. В документации (https://symfony.com/doc/current/components/security/authentication.html#authentication-events) говорится:
Событие security.interactive_login запускается после того, как пользователь активно вошел на ваш сайт. Важно отличать это действие от неинтерактивных методов аутентификации, таких как: аутентификация на основе файла cookie «запомнить меня», аутентификация на основе вашего сеанса, аутентификация с использованием базового HTTP-заголовка или дайджеста-заголовка HTTP. Вы можете прослушивать событие security.interactive_login, например, чтобы выдавать вашему пользователю приветственное флэш-сообщение каждый раз, когда он входит в систему.
Поэтому я определенно не ожидаю этого события для каждого запроса — я бы предпочел получать событие security.authentication.success
при каждом запросе, как указано в документации.
Однако класс GuardAuthenticatorHandler
Symfony отправляет событие security.interactive_login
в своем authenticateWithToken
методе, и этот метод вызывается GuardAuthenticationListener
при каждом запросе. Это ошибка в Symfony, недоразумение с моей стороны или из-за неправильной конфигурации?
(Это не философский вопрос — в моем случае он приводит к конкретной проблеме, заключающейся в том, что время последнего входа пользователя в систему обновляется при каждом запросе, что не имеет смысла.)
вы нашли решение? У меня точно такая же проблема, и я хочу чистое решение, а не упоминание о взломе ниже … — person dwytrykus schedule 20.03.2020
К сожалению, я не нашел подходящего решения. — person dwytrykus schedule 23.03.2020
Вы должны изменить это
Можете объяснить почему? Мне кажется, что запросы с аутентификацией JWT используются для разговора без сохранения состояния. — person dwytrykus; 24.05.2017
Это объясняется здесь symfony.com/doc/ current / security /, если вы устанавливаете без сохранения состояния true, вы не сохраняете аутентификацию в сеансе, и ожидается, что вы будете аутентифицироваться каждый раз. — person dwytrykus; 25.05.2017
Я столкнулся с вашей проблемой, потому что у меня точно такая же проблема. Мой обходной путь — добавить атрибут в объект запроса прямо перед возвратом true в методе поддержки охранника.
Пример:
С помощью этой информации вы можете проверить, был ли это интерактивный вход в прослушиватель событий.
Пример:
Лучше подписаться на событие
Events::JWT_CREATED
, поскольку оно запускается после прохождения аутентификации с учетными данными.Пример:
Я столкнулся с той же проблемой. В моем случае я использую аутентификацию Guard для запросов API. Так что мне определенно не нравится обновлять last_login пользователя после любого запроса API.
Событие INTERACTIVE_LOGIN отправляется из здесь..
Итак, мой грязный прием — добавить это определение в раздел
services
конфигурации приложения:Предупреждение
Очевидным недостатком этого подхода является то, что вы
сломалиобработчик изменений для всех средств защиты вашего приложения.