首页 文章

在access_control规则重定向后通知用户的最佳方法是什么?

提问于
浏览
20

来自Symfony 2.3 Security docs:

如果访问被拒绝,系统将尝试验证用户(如果尚未验证)(例如,将用户重定向到登录页面) . 如果用户已登录,将显示403“拒绝访问”错误页面 . 有关更多信息,请参见如何自定义错误页面 .

我目前正在使用 access_control 规则进行一些路由 . 我想通知匿名用户他们是否被重定向到登录路由,并显示“您必须登录才能访问该页面”的消息 . 我已经阅读了几次安全文档并且没有找到与此相关的任何内容 . 我忽略了什么吗?

如果没有,那么当他们被 access_control 规则're redirected to login (ie not if they'(如果他们只是未经授权的角色)停止时,通知用户的最佳方式是什么?

EDIT: 为了澄清,我特别询问如何检查重定向是否是由 access_control 规则引起的(如果可能的话,最好是在树枝中) .

3 回答

  • 56

    经过相当多的研究,我发现了正确的方法 . 您需要使用Entry Point服务并在防火墙配置中定义它 .

    此方法 will not mess ,您的防火墙配置中指定了default page设置,用于登录 .


    守则

    security.yml:

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

    src/Acme/UserBundle/config/services.yml

    services:
        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/Service/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'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 AuthenticationException'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">&times;</button>
                {{ flashMessage }}
            </div>
        {% endfor %}
    {% endif %}
    

    资源:

  • 1

    我认为kernel.exception监听器和设置flash消息可以做到这一点 . 未经测试的例子:

    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.');
            }
        }
    }
    

    唐't really know if it works or if it'是对的 . 您可以将其注册为 kernel.event_listener . 或者,您可能更好地使用专用服务并将其设置为firewall configaccess_denied_handler 的参数 . 我认为有很多可能的方法 .

  • 0

    你能不能只有两条登录路线?

    例如,在安全配置集中

    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>
    

相关问题