Symfony 3 - Добавление security.authorization_checker в аргументы моей службы вызывает слишком много перенаправлений

Я пытаюсь создать собственный слушатель в моем приложении 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');

    // ...
  }
}

Symfony 3 - Добавление security.authorization_checker в аргументы моей службы вызывает слишком много перенаправлений

Вы проверили, что написано в логах профилировщика?

vstm 12.06.2018 15:18

Я не могу получить к нему доступ, панель профилировщика не отображается, а URL-адрес app_dev.php/_profiler также возвращает ERR_TOO_MANY_REDIRECTS

akio 12.06.2018 15:26

Если вы закомментируете определение службы (login_listener), оно должно снова заработать. Затем вы можете щелкнуть «последние 10» запросов, и вы должны увидеть неудавшийся запрос на URL-адрес login_check.

vstm 12.06.2018 15:31

Имеется 3 информации: 1 / Соответствие маршруту входа в систему 2 / Ошибка анонимной аутентификации. 3 / Возникло исключение AuthenticationException; перенаправление к точке входа аутентификации. Я новичок в Symfony, поэтому я не уверен, что понимаю, что происходит

akio 12.06.2018 15:37

Если я закомментирую операторы if в onSecurityAuthentication, он работает, но мне нужно знать, аутентифицирован ли пользователь полностью или анонимно, тогда сделайте кое-что, но как ..?

akio 12.06.2018 15:44

Кто-нибудь мог мне помочь?

akio 14.06.2018 15:03

Хм, это всего лишь предположение, но, возможно, токена еще нет в хранилище токенов, поэтому, если вы используете метод AuthorizationChecker::isGranted, он выдаст исключение. Вы можете убедиться в этом, проверив, возвращает ли tokenstorage токен. Если токен еще не установлен, вы можете использовать AccessDecisionManager и использовать метод decide: if ($this->accessDecisionManager->decide($event->getAuthentic‌​ationToken(), ['IS_AUTHENTICATED_FULLY']))

vstm 14.06.2018 15:35

как вы и ожидали, @vstm $this->tokenStorage->getToken() пуст. Я пытался использовать ваше решение, но поскольку я новичок в Symfony, я не знаю, как использовать AccessDecisionManager в регистре слушателя в качестве службы. Не могли бы вы привести мне несколько примеров? Спасибо

akio 19.06.2018 09:27
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
8
441
1

Ответы 1

Вы можете использовать диспетчер разрешения доступа следующим образом:

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. Я не знаю, достаточно ли я понят ... извините

akio 21.06.2018 10:21

Другие вопросы по теме