猿问

使用 2 个实现 UserInterface 的实体进行身份验证

是否有可能有 2 个实体实现UserInterface

如何在我的警卫上使用它来使其在两个类中检查并使用相同的防火墙?

这个想法是公司可以拥有CVTheque或共享它(CVTheque与 具有 OneToMany 关系Company)。

我想拥有CandidateUser实体。

  • CVTheque -> OneToMany -> 候选人

  • 用户 -> 多对一 -> 公司。

Candidate并将User使用相同的登录表单在应用程序上进行身份验证。所以我不知道这是否可能以及如何在我的警卫身份验证器上实现这一点。

Candidate根据连接用户的实例(或User),它们将被重定向到自己的仪表板。


撒科打诨
浏览 74回答 2
2回答

莫回无

最近处理了类似的情况。在我的例子中,刚刚创建了一个chain_provider来封装所有需要的实体:providers:    chain_provider:        chain:            providers: [provider_one, provider_two]    provider_one:        entity:            class: App\Entity\ProviderOne            property: username    provider_two:        entity:            class: App\Entity\ProviderTwo            property: emailsecurity:    firewalls:        secured_area:            # ...            pattern: ^/login            provider: chain_provider

ibeautiful

我相信这是可能的,让我们采用基本的用户身份验证并尝试对其进行调整<?phpnamespace App\Security;use App\Entity\User;use Doctrine\ORM\EntityManagerInterface;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\Security\Core\Security;use Symfony\Component\Security\Csrf\CsrfToken;use Symfony\Component\EventDispatcher\GenericEvent;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\Security\Core\User\UserInterface;use Symfony\Component\Security\Http\Util\TargetPathTrait;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;use Symfony\Component\Security\Core\User\UserProviderInterface;use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;class LoginAuthenticator extends AbstractFormLoginAuthenticator{&nbsp; &nbsp; use TargetPathTrait;&nbsp; &nbsp; private $entityManager;&nbsp; &nbsp; private $urlGenerator;&nbsp; &nbsp; private $csrfTokenManager;&nbsp; &nbsp; private $encoder;&nbsp; &nbsp; public function __construct(&nbsp; &nbsp; &nbsp; &nbsp; EntityManagerInterface $entityManager,&nbsp; &nbsp; &nbsp; &nbsp; UrlGeneratorInterface $urlGenerator,&nbsp; &nbsp; &nbsp; &nbsp; CsrfTokenManagerInterface $csrfTokenManager,&nbsp; &nbsp; &nbsp; &nbsp; UserPasswordEncoderInterface $encoder)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $this->entityManager = $entityManager;&nbsp; &nbsp; &nbsp; &nbsp; $this->urlGenerator = $urlGenerator;&nbsp; &nbsp; &nbsp; &nbsp; $this->csrfTokenManager = $csrfTokenManager;&nbsp; &nbsp; &nbsp; &nbsp; $this->encoder = $encoder;&nbsp; &nbsp; &nbsp; &nbsp; $this->eventDispatcher = $eventDispatcher;&nbsp; &nbsp; }&nbsp; &nbsp; public function supports(Request $request)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'login' === $request->attributes->get('_route')&& $request->isMethod('POST') // here you need to specify the other login route if you want to have 2 seperate ones&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }&nbsp; &nbsp; public function getCredentials(Request $request)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $credentials = [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'username' => $request->request->get('username'),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'password' => $request->request->get('password'),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'csrf_token' => $request->request->get('_csrf_token'),&nbsp; &nbsp; &nbsp; &nbsp; ];&nbsp; &nbsp; &nbsp; &nbsp; $request->getSession()->set(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Security::LAST_USERNAME,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $credentials['username']&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; &nbsp; &nbsp; return $credentials;&nbsp; &nbsp; }&nbsp; &nbsp; public function getUser($credentials, UserProviderInterface $userProvider)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; $token = new CsrfToken('authenticate', $credentials['csrf_token']);&nbsp; &nbsp; &nbsp; &nbsp; if (!$this->csrfTokenManager->isTokenValid($token)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new InvalidCsrfTokenException();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; $user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $credentials['username']]);&nbsp; &nbsp; &nbsp; &nbsp; if (!$user) { // here look for user in the 2nd entity, if it will still be null throw the exception&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // fail authentication with a custom error&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new CustomUserMessageAuthenticationException('Username could not be found.');&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return $user;&nbsp; &nbsp; }&nbsp; &nbsp; public function checkCredentials($credentials, UserInterface $user)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->encoder->isPasswordValid($user, $credentials['password'], $user->getSalt());&nbsp; &nbsp; }&nbsp; &nbsp; public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new RedirectResponse($targetPath);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return new RedirectResponse($this->urlGenerator->generate('account_index'));&nbsp; &nbsp; }&nbsp; &nbsp; protected function getLoginUrl()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return $this->urlGenerator->generate('login');&nbsp; &nbsp; }}大概就是这样,我们将身份验证器更改为支持2个路由(登录一个,登录两个),如果第一个实体与用户名和密码不匹配,请尝试在另一个实体中查找用户,您不妨添加一个隐藏输入或根据路由在请求侦听器中添加属性,使用 RequestStack 检索它,或者您想要指示每个实体。
随时随地看视频慕课网APP
我要回答