如何立即禁用对被软删除或不再启用的用户的访问?
How to immediately disable access to a user that is soft-deleted or no longer enabled?
在我的应用程序中,具有 ROLE_ADMIN
角色的用户可以手动禁用其他用户帐户,方法是将用户帐户上的 enabled
设置为 false。
使用 user checker,用户将无法在下次尝试登录时登录:
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");
}
但这似乎是一个糟糕的解决方案,因为我在很多地方都需要它。
如果您在用户 class 中实施 Symfony\Component\Security\Core\User\EquatableInterface
,the User will be logged out when isEqualTo()
returns 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;
}
/* ... */
}
我听从了 Cerad 的建议,并添加了一个监听器,如下所示。但是,要获得更好的(内置)解决方案,请参阅 Pete 的回答。
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));
}
}
}
在我的应用程序中,具有 ROLE_ADMIN
角色的用户可以手动禁用其他用户帐户,方法是将用户帐户上的 enabled
设置为 false。
使用 user checker,用户将无法在下次尝试登录时登录:
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");
}
但这似乎是一个糟糕的解决方案,因为我在很多地方都需要它。
如果您在用户 class 中实施 Symfony\Component\Security\Core\User\EquatableInterface
,the User will be logged out when isEqualTo()
returns 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;
}
/* ... */
}
我听从了 Cerad 的建议,并添加了一个监听器,如下所示。但是,要获得更好的(内置)解决方案,请参阅 Pete 的回答。
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));
}
}
}