Как немедленно отключить доступ к пользователю, который удален или больше не включен? - PullRequest
3 голосов
/ 04 апреля 2020

В моем приложении пользователи с ролью ROLE_ADMIN могут вручную отключить учетные записи других пользователей, установив для enabled в учетной записи пользователя значение false.

Используя пользовательскую проверку , пользователь не сможет войти в систему при следующей попытке:

public function checkPostAuth(UserInterface $user)
{
    if (!$user->isEnabled()) {
        throw new CustomUserMessageAuthenticationException(
            'Account is not enabled.'
        );
    }
}

Моя проблема с этим, она работает только тогда, когда пользователь пытается войти в систему. Если пользователь в настоящее время вошел в систему (может также использовать функцию запомнить меня), ничего не произойдет, пока он не выйдет из системы.

Есть ли способ немедленно отключить пользователя от отправки запросов на маршруты, к которым у него больше нет доступа, даже если этот пользователь в данный момент вошел в систему?

Что я мог сделать, это проверить, учетная запись включена для каждого маршрута, для которого требуется доступ этого пользователя, например:

if ($this->getUser()->isEnabled() === false) {
    throw new \Exception("Account disabled");
}

Но это кажется ужасным решением, потому что мне это понадобится во многих местах.

Ответы [ 2 ]

2 голосов
/ 04 апреля 2020

Если вы реализуете Symfony\Component\Security\Core\User\EquatableInterface в своем классе пользователя, , пользователь выйдет из системы, когда isEqualTo() вернет false .

class User implements Symfony\Component\Security\Core\User\EquatableInterface
{
    /* ... */

    public function isEqualTo(UserInterface $user)
    {
        if (!$user instanceof User) {
            return false;
        }

        if ($this->enabled !== $user->enabled) {
            // Forces the user to log in again if enabled 
            // changes from true to false or vice-versa.
            // This could be replaced by a more sophisticated comparison.
            return false;
        }

        // do a bunch of other checks, such as comparing the 
        // password hash: this will cause the user to be logged 
        // out when their password is changed.

        return true;
    }

    /* ... */
}

Соответствующая документация

1 голос
/ 04 апреля 2020

Я последовал совету Керада и добавил слушателя, как видно ниже. Однако, для лучшего (встроенного) решения, смотрите ответ Пита.

namespace App\EventListener;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\RequestEvent;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Security;

class RequestListener
{

    private $security; // needed to get the user
    private $router; // needed to generate the logout-url

    public function __construct(Security $security, UrlGeneratorInterface $router) 
    {
        $this->security = $security;
        $this->router = $router;
    }

    public function __invoke(RequestEvent $event) : void
    {
        $user = $this->security->getUser();

        // Don't do anything if no user is logged in.
        if ($user === null) {
            return;
        }

        if ($user->isEnabled() === false) {
            // Generate the logout url based on the path name and redirect to it.
            $url = $this->router->generate('app_logout');
            $event->setResponse(new RedirectResponse($url));
        }
    }
}
...