Symfony 5:如何在登录前检查用户是不是被禁止
Posted
技术标签:
【中文标题】Symfony 5:如何在登录前检查用户是不是被禁止【英文标题】:Symfony 5 : how to check if user is banned or not before loginSymfony 5:如何在登录前检查用户是否被禁止 【发布时间】:2021-01-04 20:04:15 【问题描述】:我正在开发一个 symfony 5 项目和一个带有安全组件的身份验证系统,我在我的用户实体中添加了一个名为 is_banned 的字段,默认情况下它采用 false 值,我想放置一个函数来检查是否用户在登录之前是否被禁止,如果是,则应用将其重定向到主页并显示简单的错误消息!
<?php
namespace App\Entity;
/**
* @ORM\Entity(repositoryClass=UserRepository::class)
* @UniqueEntity(fields="email", message="There is already an account with this email")
*/
class User implements UserInterface
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=180, unique=true)
*/
private $email;
/**
* @ORM\Column(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORM\Column(type="string")
*/
private $password;
/**
* @ORM\Column(type="boolean")
*/
private $isVerified = false;
/**
* @ORM\Column(type="boolean")
*/
private $is_banned = false;
public function __construct()
$this->bookings = new ArrayCollection();
$this->roles = array('ROLE_USER');
public function getId(): ?int
return $this->id;
public function getEmail(): ?string
return $this->email;
public function setEmail(string $email): self
$this->email = $email;
return $this;
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
return (string) $this->email;
/**
* @see UserInterface
*/
public function getRoles(): array
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
public function setRoles(array $roles): self
$this->roles = $roles;
return $this;
/**
* @see UserInterface
*/
public function getPassword(): string
return (string) $this->password;
public function setPassword(string $password): self
$this->password = $password;
return $this;
/**
* @see UserInterface
*/
public function getSalt()
// not needed when using the "bcrypt" algorithm in security.yaml
/**
* @see UserInterface
*/
public function eraseCredentials()
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
public function isVerified(): bool
return $this->isVerified;
public function setIsVerified(bool $isVerified): self
$this->isVerified = $isVerified;
return $this;
public function getIsBanned(): ?bool
return $this->is_banned;
public function setIsBanned(bool $is_banned): self
$this->is_banned = $is_banned;
return $this;
<?php
namespace App\Security;
class UserAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
public function supports(Request $request)
return self::LOGIN_ROUTE === $request->attributes->get('_route')
&& $request->isMethod('POST');
public function getCredentials(Request $request)
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
public function getUser($credentials, UserProviderInterface $userProvider)
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token))
throw new InvalidCsrfTokenException();
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
if (!$user)
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
return $user;
public function checkCredentials($credentials, UserInterface $user)
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
/**
* Used to upgrade (rehash) the user's password automatically over time.
* @param $credentials
* @return string|null
*/
public function getPassword($credentials): ?string
return $credentials['password'];
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey))
return new RedirectResponse($targetPath);
return new RedirectResponse($this->urlGenerator->generate('car.index'));
//throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
protected function getLoginUrl()
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
【问题讨论】:
那么你有什么尝试?你知道你生成的验证器实际上在做什么吗?授权应该是身份验证的一部分吗? 【参考方案1】:您可以使用用户检查器。它会在登录表单上抛出错误:
config/packages/security.yaml
security:
...
firewalls:
...
main:
...
user_checker: App\Security\UserChecker
App\Security\UserChecker
namespace App\Security;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
class UserChecker implements UserCheckerInterface
public function checkPreAuth(UserInterface $user)
if ($user->getIsBanned())
throw new CustomUserMessageAuthenticationException("You're banned !");
public function checkPostAuth(UserInterface $user)
【讨论】:
以上是关于Symfony 5:如何在登录前检查用户是不是被禁止的主要内容,如果未能解决你的问题,请参考以下文章
Symfony - 如何将用户重定向到登录后访问的最后一个页面?
如何使用 MVC 5 在基于令牌的身份验证中检查用户是不是从控制器登录?
如何在事件订阅者中访问Symfony 3.3中的登录用户,而不会丢失Web分析器