Подтвердить что ты не робот

Каков наилучший способ уведомления пользователя после перенаправления правила access_control?

От Symfony 2.3 Безопасность docs:

Если доступ запрещен, система попытается аутентифицировать пользователя, если он еще не был (например, перенаправить пользователя на страницу входа). Если пользователь уже вошел в систему, отобразится страница с ошибкой 403 "отказ от доступа". См. Раздел "Настройка страниц ошибок" для получения дополнительной информации.

В настоящее время я использую правило access_control для нескольких маршрутов. Я хотел бы уведомить анонимного пользователя, если они перенаправлены на маршрут входа в систему с таким сообщением, как "Вы должны войти в систему, чтобы получить доступ к этой странице". Я несколько раз читал документы по безопасности и не нашел ничего подходящего для этого. Я что-то пропускаю?

Если нет, то каким образом было бы лучше всего уведомить пользователя, когда оно остановлено с помощью правила access_control только, если они перенаправлены на вход в систему (т.е. нет, если они просто в несанкционированной роли)?

EDIT: Для уточнения, я специально спрашиваю, как проверить, было ли перенаправление вызвано правилом access_control (желательно, если возможно, на ветке).

4b9b3361

Ответ 1

Итак, после довольно много исследований я нашел правильный способ сделать это. Вам необходимо использовать службу Entry Point и определить ее в конфигурации брандмауэра.

Этот метод не будет помещать с настройками по умолчанию, указанными в конфигурации вашего брандмауэра для входа в систему.


Код

security.yml:

firewalls:
    main:
        entry_point: entry_point.user_login #or whatever you name your service
        pattern: ^/
        form_login:
        # ...

SRC/Акме/UserBundle/конфигурации/services.yml

entry_point.user_login:
    class: Acme\UserBundle\Service\LoginEntryPoint
    arguments: [ @router ] #I am going to use this for URL generation since I will be redirecting in my service

ЦСИ/Acme/UserBundle/Услуги/LoginEntryPoint.php:

namespace Acme\UserBundle\Service;

use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface,
    Symfony\Component\Security\Core\Exception\AuthenticationException,
    Symfony\Component\HttpFoundation\Request,
    Symfony\Component\HttpFoundation\RedirectResponse;

 /**
 * When the user is not authenticated at all (i.e. when the security context has no token yet), 
 * the firewall entry point will be called to start() the authentication process. 
 */

class LoginEntryPoint implements AuthenticationEntryPointInterface{

     protected $router;

    public function __construct($router){
        $this->router = $router;

    }
     /*
     * This method receives the current Request object and the exception by which the exception 
     * listener was triggered. 
     * 
     * The method should return a Response object
     */

    public function start(Request $request, AuthenticationException $authException = null){
        $session = $request->getSession();

        //I am choosing to set a FlashBag message with my own custom message.
        //Alternatively, you could use AuthenticaionException generic message 
        //by calling $authException->getMessage()
        $session->getFlashBag()->add('warning', 'You must be logged in to access that page');

        return new RedirectResponse($this->router->generate('login'));
    }
}

login.html.twig:

{# bootstrap ready for your convenience ;] #}
{% if app.session.flashbag.has('warning') %}
    {% for flashMessage in app.session.flashbag.get('warning') %}
        <div class="alert alert-warning">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ flashMessage }}
        </div>
    {% endfor %}
{% endif %}

Ресурсы:

Ответ 2

Я думаю, что kernel.exception прослушиватель и установка флеш-сообщения может это сделать. Непритянутый пример:

use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;

class My403ExceptionListener
{
    protected $session;

    public function __construct(SessionInterface $session)
    {
        $this->session = $session;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        $exception = $event->getException();
        if ($exception instanceof AccessDeniedHttpException) {
            $this->session->getFlashBag()->set('warning', 'You must login to access that page.');
        }
    }
}

Не знаю, работает ли это или правильно. Вы можете зарегистрировать его как kernel.event_listener. Или, может быть, вам лучше назначить выделенный сервис и установить его как параметр access_denied_handler в конфигурации firewall. Я думаю, что существует множество возможных путей.

Ответ 3

Не могли бы вы просто иметь два логина?

Например, в настройке конфигурации безопасности

form_login:
    login_path: /login_message

В вашем контроллере входа в систему

/**
 * @Template()
 * @Route("/notauthorized", name="login_message")
 */
 public function loginMessageAction()
 {
    return [];
 }

И затем в вашем loginMessage.html.twg

<a href="{{ path('login') }}">You must login to access this page.</a>