【问题标题】:What is the best way to notify a user after an access_control rule redirects?在 access_control 规则重定向后通知用户的最佳方式是什么?
【发布时间】:2013-06-30 00:30:42
【问题描述】:

来自Symfony 2.3 Security docs:

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

我目前正在为几条路线使用access_control 规则。如果匿名用户被重定向到登录路径,我想通知他们,并显示“您必须登录才能访问该页面”之类的消息。我已经阅读了几次安全文档,但没有发现任何与此相关的内容。我忽略了什么吗?

如果不是,当用户被access_control 规则阻止时通知用户的最佳方式是,如果他们被重定向到登录(即,如果他们只是以未经授权的角色)?

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

【问题讨论】:

    标签: php symfony redirect twig access-control


    【解决方案1】:

    我采用不同的方法,在控制器中我抛出新的AuthenticationException,然后在 flashbag 中添加错误消息。

    // Check if user is logged in.
    if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED') == FALSE) {
      $request->getSession()
        ->getFlashBag()
        ->add('error', "Please login to continue");
      throw new AuthenticationException();
    }
    

    并在登录树枝模板中,显示消息。

    {% for flash_message in app.session.flashBag.get('error') %}
      <div class="callout alert" role="alert">
        {{ flash_message }}
      </div>
    {% endfor %}
    

    【讨论】:

      【解决方案2】:

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

      此方法不会混淆您在防火墙配置中为登录指定的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 %}
      

      资源:

      【讨论】:

      • 不错的嘉莉,真是一场噩梦!
      • 干得好。节省了我很多时间!
      • 不完全是我的目标,但是,对于类似的问题非常有帮助!谢谢!
      【解决方案3】:

      我认为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。或者,您最好编写一个专用服务并将其设置为firewall configaccess_denied_handler 的参数。我认为有很多可能的方法。

      【讨论】:

      • 永远不会为重定向触发 access_denied_handler,只会在未经授权的情况下触发
      • 是的,它在搜索结果中非常模糊,并且文档对它的描述非常少。我可能会提交补丁
      【解决方案4】:

      你不能只有两条登录路径吗?

      例如,在安全配置集中

      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>
      

      【讨论】:

      • 虽然这是一种可能,但我特意寻找一种处理 access_control 规则的方法。这是一种解决方法,但不是真正的解决方案
      • 是的,我写它的时候也有同样的感觉。我确信有一种“非黑客”的方式来做到这一点,我只是不确定如何
      • 检查我的答案以获得干净的无黑客解决方案:D
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-23
      • 2019-01-29
      • 1970-01-01
      相关资源
      最近更新 更多