Из документов Symfony 2.3 Security :
Если доступ запрещен, система попытается аутентифицировать пользователя, если он еще не был (например, перенаправить пользователя на страницу входа) . Если пользователь уже вошел в систему, отобразится страница с ошибкой 403 «отказ от доступа». См. Раздел «Настройка страниц ошибок» для получения дополнительной информации.
- FOSRestBundle: показать мое пользовательское сообщение об исключении
- Вызов неопределенной функции Symfony \ Polyfill \ Mbstring \ iconv_strlen ()
- Как создать динамическую ассоциацию сущностей с Doctrine2 в Symfony2
- Pheanstalk не выполняет работу
- Кэш-память Symfony 2: результаты запроса Doctrine
- Doctrine 2 WHERE IN, используя набор объектов
В настоящее время я использую правило access_control
для нескольких маршрутов. Я хотел бы уведомить анонимного пользователя, если они перенаправлены на маршрут входа в систему с таким сообщением, как « Вы должны войти в систему, чтобы получить доступ к этой странице ». Я несколько раз читал документы по безопасности и не нашел ничего подходящего для этого. Я что-то пропускаю?
Если нет, то каким образом можно было бы уведомить пользователя, когда они будут остановлены правилом access_control
только если они перенаправлены на вход в систему (т. access_control
Нет, если они просто неавторизированы )?
EDIT: Для уточнения, я специально спрашиваю, как проверить, было ли перенаправление вызвано правилом access_control
(желательно, если возможно, на access_control
).
Поэтому после довольно много исследований я нашел правильный способ сделать это. Вам нужно будет использовать службу точки входа и определить ее в конфигурации брандмауэра.
Этот метод не будет связываться с вашими настройками по умолчанию , указанными в конфигурации вашего брандмауэра, для входа в систему.
security.yml:
firewalls: main: entry_point: entry_point.user_login #or whatever you name your service pattern: ^/ form_login: # ...
SRC / Acme / 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
SRC / 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 (ie when the security context has no token yet), * the firewall's 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's 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">×</button> {{ flashMessage }} </div> {% endfor %} {% endif %}
Я думаю, что прослушиватель 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
в конфигурации брандмауэра . Я думаю, что существует множество возможных путей.
Могли бы вы не просто иметь два логина?
Например, в настройке конфигурации безопасности
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>