Я пытаюсь создать собственный слушатель в моем приложении Symfony 3.
Я хочу проверить, является ли пользователь IS_AUTHENTICATED_FULLY или нет.
Когда я добавляю службу @security.authorization_checker в качестве аргумента к моему, я получаю "слишком много ошибок перенаправления" для моего маршрута входа
У кого-нибудь есть рабочее решение в Symfony 3?
security.yml:
security:
providers:
main:
entity:
class: Customer\CustomerBundle\Entity\utilisateur
property: loginUtil
encoders:
Customer\CustomerBundle\Entity\utilisateur:
algorithm: sha1
encode_as_base64: false
iterations: 1
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
Customer_firewall:
pattern: ^/
anonymous: true
provider: main
form_login:
login_path: /login
check_path: /login_check
logout:
path: /logout
target: Customer_standard_homepage
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reset, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile, roles: ROLE_USER }
role_hierarchy:
ROLE_ADMIN : [ROLE_USER]
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
Services.yml
services:
login_listener:
class: 'Customer\CustomerBundle\Listener\LoginListener'
arguments: ['@security.authorization_checker', '@doctrine']
tags:
- { name: 'kernel.event_listener', event: 'security.authentication.success', method: onSecurityAuthentication }
LoginListener.php
<?php
namespace Customer\CustomerBundle\Listener;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
/**
* Custom login listener.
*/
class LoginListener
{
private $authorizationChecker;
private $em;
public function __construct(AuthorizationChecker $authorizationChecker, Doctrine $doctrine)
{
$this->authorizationChecker = $authorizationChecker;
$this->em = $doctrine->getEntityManager();
}
/**
* Do the magic.
*
* @param InteractiveLoginEvent $event
*/
public function onSecurityAuthentication(AuthenticationEvent $event)
{
if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_FULLY')) {
// user has just logged in
error_log('here');
}
if ($this->authorizationChecker->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
// user has logged in using remember_me cookie
error_log('there');
}
// do some other magic here
$user = $event->getAuthenticationToken()->getUser();
error_log('FINALLY HERE');
// ...
}
}
Я не могу получить к нему доступ, панель профилировщика не отображается, а URL-адрес app_dev.php/_profiler также возвращает ERR_TOO_MANY_REDIRECTS
Если вы закомментируете определение службы (login_listener), оно должно снова заработать. Затем вы можете щелкнуть «последние 10» запросов, и вы должны увидеть неудавшийся запрос на URL-адрес login_check.
Имеется 3 информации: 1 / Соответствие маршруту входа в систему 2 / Ошибка анонимной аутентификации. 3 / Возникло исключение AuthenticationException; перенаправление к точке входа аутентификации. Я новичок в Symfony, поэтому я не уверен, что понимаю, что происходит
Если я закомментирую операторы if в onSecurityAuthentication, он работает, но мне нужно знать, аутентифицирован ли пользователь полностью или анонимно, тогда сделайте кое-что, но как ..?
Кто-нибудь мог мне помочь?
Хм, это всего лишь предположение, но, возможно, токена еще нет в хранилище токенов, поэтому, если вы используете метод AuthorizationChecker::isGranted, он выдаст исключение. Вы можете убедиться в этом, проверив, возвращает ли tokenstorage токен. Если токен еще не установлен, вы можете использовать AccessDecisionManager и использовать метод decide: if ($this->accessDecisionManager->decide($event->getAuthenticationToken(), ['IS_AUTHENTICATED_FULLY']))
как вы и ожидали, @vstm $this->tokenStorage->getToken() пуст. Я пытался использовать ваше решение, но поскольку я новичок в Symfony, я не знаю, как использовать AccessDecisionManager в регистре слушателя в качестве службы. Не могли бы вы привести мне несколько примеров? Спасибо






Вы можете использовать диспетчер разрешения доступа следующим образом:
use Symfony\Bridge\Doctrine\RegistryInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Symfony\Component\Security\Core\Event\AuthenticationEvent;
class LoginListener
{
private $accessDecisionManager;
private $doctrine;
public function __construct(AccessDecisionManagerInterface $accessDecisionManager, RegistryInterface $doctrine)
{
$this->accessDecisionManager = $accessDecisionManager;
$this->doctrine = $doctrine;
}
/**
* Do the magic.
*
* @param AuthenticationEvent $event
*/
public function onSecurityAuthentication(AuthenticationEvent $event)
{
$em = $this->doctrine->getEntityManager();
if ($this->accessDecisionManager->decide($event->getAuthenticationToken(), ['IS_AUTHENTICATED_FULLY'])) {
error_log('here');
}
if ($this->accessDecisionManager->decide($event->getAuthenticationToken(), ['IS_AUTHENTICATED_REMEMBERED'])) {
// user has logged in using remember_me cookie
error_log('there');
}
// do some other magic here
$user = $event->getAuthenticationToken()->getUser();
error_log('FINALLY HERE');
// ...
}
}
И определение службы нужно изменить на это:
login_listener:
class: 'Customer\CustomerBundle\Listener\LoginListener'
arguments: ['@security.access.decision_manager', '@doctrine']
tags:
- { name: 'kernel.event_listener', event: 'security.authentication.success', method: onSecurityAuthentication }
Я также немного изменил конструктор, в общем, при использовании внедрения зависимостей рекомендуется ссылаться на интерфейс, если это возможно. Также конструктор не должен делать слишком много вещей (я удалил вызов getEntityManger() и переместил id в слушатель).
Потрясающе, как и ожидалось. Но я понял, что мой ивент security.authentication.success - не лучший выбор для моих нужд. Поэтому я решил использовать событие kernel.controller, но теперь я потерял доступ к AuthenticationEvent, чтобы получить getAuthenticationToken внутри onSecurityAuthentication. Я не знаю, достаточно ли я понят ... извините
Вы проверили, что написано в логах профилировщика?