如何从 Symfony 5 中的请求获取防火墙名称?

mic*_*vka 3 php symfony symfony5

问题很简单。我正在实施AccessDeniedListener并得到一个ExceptionEvent对象。从这里我可以得到请求。仅当我位于 security.yaml 中定义的防火墙之一内时,我才想应用某些逻辑。

ExceptionEvent如何从实例获取防火墙名称Request

编辑:我发现这段代码“有效”

$firewall_context_name = $event->getRequest()->attributes->get('_firewall_context');
Run Code Online (Sandbox Code Playgroud)

不过我对此不太高兴。应该有一个FirewallContextFirewallConfig多个对象可以以某种方式检索,不是吗?谢谢

class AccessDeniedListener implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            // the priority must be greater than the Security HTTP
            // ExceptionListener, to make sure it's called before
            // the default exception listener
            KernelEvents::EXCEPTION => ['onKernelException', 2],
        ];
    }
    
    public function onKernelException(ExceptionEvent $event): void
    {
        $exception = $event->getThrowable();
        if (!$exception instanceof AccessDeniedException) {
            return;
        }
        
        $request = $event->getRequest();

        // HOW TO GET FIREWALL NAME HERE???

Run Code Online (Sandbox Code Playgroud)

安全.yaml

   firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        api:
            pattern: ^/api/
            security: false
        main:
            custom_authenticators:
                - App\Security\LoginFormAuthenticator
            logout:
                path: app_logout
            lazy: true
            provider: app_user_provider
Run Code Online (Sandbox Code Playgroud)

msg*_*msg 5

正如您链接的文档中所述:

可以通过类getFirewallConfig(Request $request)的方法 访问该对象Symfony\Bundle\SecurityBundle\Security\FirewallMap

此类无法直接注入,因此您必须在services.yaml使用服务别名时配置依赖项security.firewall.map(或者如果您打算在其他地方使用它,则创建一个服务别名)。

services:
  # ...
  App\Listener\AccessDeniedListener:
    arguments:
      $firewallMap: '@security.firewall.map'
Run Code Online (Sandbox Code Playgroud)

现在修改您的侦听器以接收此参数:

class AccessDeniedListener implements EventSubscriberInterface
{
    private $firewallMap;

    public function __construct(FirewallMapInterface $firewallMap)
    {
        $this->firewallMap = $firewallMap;
    }

    // Ommited getSubscribedEvents
    
    public function onKernelException(ExceptionEvent $event): void
    {
        $request = $event->getRequest();

        $firewallConfig = $this->firewallMap->getFirewallConfig($request);

        if (null === $firewallConfig) {
            return;
        }
        $firewallName = $firewallConfig->getName();
     }
}
Run Code Online (Sandbox Code Playgroud)