Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Security] Add an easier way to get the current firewall name #46015

Closed
@alexander-schranz

Description

@alexander-schranz

Description

Depending on the used firewall I want to implement some logic. Currently there is no good way to get the current name of the firewall.

The firewall listener does set a attribute called _firewall_context which is for example firewall name extranet something like security.firewall.map.context.extranet so it would be something like if (str_ends_with(... check which feels very strange.

Also in my case the _firewall_context attribute is not set at the time I need to register mycustom listener. I need to control a custom $request->attribute depending on the firewall name before the UserProvider is called. It seems the listener which calls the UserProvider and is setting the _firewall_context is the same. So no way to inject between.

The current workaround here I found:

This requires to inject the FirewallMap and call a method which is not part of the FirewallMapInterface and so can make problems if is somebody would decorate that service (logger).

What would be the expected behaviour. I think the best would be have first a listener which would set the a _firewall_name attribute on the $request object. With a higher priority then the FirewallListener itself. So somebody can create a listener between matching of the firewall and calling firewall specific logic (userprovider, login, logout, ...).

Another way would providing an additoinal method on the Security service to return the current FirewallName.

Example

Custom Listener

This shows the following example of such a listener

<?php

declare(strict_types=1);

namespace App\Access\Infrastructure\Sulu\Security;

use App\Access\Infrastructure\Sulu\Admin\ExtranetAdmin;
use Sulu\Bundle\SecurityBundle\System\SystemStoreInterface;
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Security\Http\FirewallMapInterface;

class SecuritySystemSubscriber implements EventSubscriberInterface
{
    private FirewallMap $map;

    private SystemStoreInterface $systemStore;

    public function __construct(
        SystemStoreInterface $systemStore,
        FirewallMapInterface $map,
    ) {
        $this->systemStore = $systemStore;

        if (!$map instanceof FirewallMap) {
            throw new \LogicException(\sprintf('Expected "%s" but got "%s".', FirewallMap::class, \get_class($map)));
        }

        $this->map = $map;
    }

    public static function getSubscribedEvents(): array
    {
        return [
            KernelEvents::REQUEST => [
                // need to be after @see \Sulu\Bundle\SecurityBundle\EventListener\SystemListener::getSubscribedEvents
                // need to be before @see \Symfony\Bundle\SecurityBundle\EventListener\FirewallListener::getSubscribedEvents
                ['processSecuritySystem', 9],
            ],
        ];
    }

    public function processSecuritySystem(RequestEvent $event): void
    {
        if (!$event->isMainRequest()) {
            return;
        }

        // this is strange as it is not part of the FirewallMapInterface
        $config = $this->map->getFirewallConfig($event->getRequest());
        if (!$config) {
            return;
        }

        if ('extranet' === $config->getName()) {
            $this->systemStore->setSystem(ExtranetAdmin::SYSTEM);
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    DXDX = Developer eXperience (anything that improves the experience of using Symfony)FeatureSecurity

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions