【问题标题】:Symfony2: Check user authentication based on pathSymfony2:根据路径检查用户身份验证
【发布时间】:2013-11-25 12:34:11
【问题描述】:

在 Symfony2 中,是否可以检查用户是否经过身份验证以访问他请求的 URl。 我想要做的是,我不想让登录用户返回注册或登录或恢复密码页面。

这是我的 security.yml:

    access_control:
    - { path: ^/signup/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/register/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}
    - { path: ^/recover/, roles: IS_AUTHENTICATED_ANONYMOUSLY && !IS_AUTHENTICATED_FULLY}

但这显示,当前用户访问被拒绝页面。所以我认为如果我可以通过检查他是否被允许将用户重定向到此类请求的主页,那将是很好的。我可以通过提供用户在侦听器中是否经过身份验证的路径来检查吗?

    public function onKernelResponse(FilterResponseEvent $event)
    {
     $request = $event->getRequest();
     $path = $request->getPathInfo();

     if($this->container->get('security.context')->getToken() != null) {
       // To check if user is authenticated or anonymous
       if( ($this->container->get('security.context')->getToken() instanceof UsernamePasswordToken) &&
        ($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') == true) ) {
         // HOW TO CHECK PATH ?
        // set response to redirect to home page
      }
    }
  }

【问题讨论】:

  • 为什么使用onKernelResponse 事件而不是kernel.request.event
  • 是的,你是对的。我应该在 kernel.request.event 中检查它,谢谢。

标签: php symfony authentication


【解决方案1】:

security.access_map 服务

security.access_control的配置由...处理

SecurityBundle\DependencyInjection\SecurityExtension

... 为路由(路径、主机、ip、...)创建 RequestMatchers,然后使用匹配器、允许的角色和通道(即 https )调用服务的 add() 方法。

该服务通常由AccessListener使用。

您可以使用 security.access_map 服务访问 security.access_control 应用程序中的参数。

security.access_map 服务使用的类由参数security.access_map.class 定义,默认为

Symfony\Component\Security\Http\AccessMap ( 实现 AccessMapInterface)

您可以使用参数 security.access_map.class 来使用自定义类覆盖服务(必须实现 AccessMapInterface):

# i.e. app/config/config.yml

parameters:
    security.access_map.class: My\Custom\AccessMap

如何访问服务

security.access_map 服务是一个私有服务,正如您所看到的其定义 here

这意味着您不能像这样直接从容器中请求它:

$this->container->get('security.access_map')

您必须明确地将其注入到另一个服务(即侦听器服务)中才能访问它。


监听器示例

services:
    my_listener:
        class: My\Bundle\MyListenerBundle\EventListener\ForbiddenRouteListener
        arguments: [ @security.access_map ]
        tags:      
            - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

然后您可以调用getPatterns() 方法从那里获取RequestMatchers、允许的角色和所需的频道。

namespace My\Bundle\MyListenerBundle\EventListener;

use Symfony\Component\Security\Http\AccessMapInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;

class ForbiddenRouteListener
{

    protected $accessMap;

    public function __construct(AccessMapInterface $access_map)
    {
        $this->accessMap = $access_map;
    }

    public function onKernelRequest(GetResponseEvent $event)
    {
        $request = $event->getRequest();
        $patterns = $this->accessMap->getPatterns($request);

        // ...

【讨论】:

  • 稍后我将不得不继续使用完整的解决方案 - 抱歉。但这应该已经暗示了正确的方向。
  • 感谢access_map服务的详细说明。我还没有尝试过,但这会奏效。
  • 彻底回答,很好!
【解决方案2】:

也许这会对某人有所帮助。我只是捕获路线名称并检查它们是否在数组中。如果是,只需重定向。这是事件监听器。

services.yml

project.loggedin_listener:
      class: Project\FrontBundle\EventListener\LoggedInListener
      arguments: [ "@router", "@service_container" ]
      tags:
        - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }

听众:

namespace Project\FrontBundle\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;

class LoggedInListener {
    private $router;
    private $container;

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

    public function onKernelRequest(GetResponseEvent $event)
    {
        $container = $this->container;
        $accountRouteName = "_homepage";

        if( $container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY') ){

            $routeName = $container->get('request')->get('_route');
            $routes = array("admin_login","fos_user_security_login","fos_user_registration_register","fos_user_resetting_request");
            if(in_array($routeName, $routes)){
                $url = $this->router->generate($accountRouteName);
                $event->setResponse(new RedirectResponse($url));
            }

        }

    }
}

【讨论】:

  • 在 symfony 2.6 security.context 已弃用,需要使用 security.authorization_checker
【解决方案3】:

您不仅可以在 security.yml 选项中执行此操作,还可以通过控制器执行此操作,如下所示:

if($securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
      return $this->redirect($this->generateUrl('homepage'));
}

【讨论】:

猜你喜欢
  • 2012-06-07
  • 1970-01-01
  • 2022-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多