Я аутентифицирую свое приложение с помощью класса, который расширяет AbstractFormLoginAuthenticator. Форма входа имеет поля электронной почты и пароля. Мне нужно иметь жестко запрограммированного пользователя в памяти и иметь возможность войти в систему через эту форму входа. Как я могу настроить файл безопасности, чтобы это работало?
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
private $userRepository;
private $router;
private $passwordEncoder;
public function __construct(UserRepository $userRepository, RouterInterface $router, UserPasswordEncoderInterface $passwordEncoder)
{
$this->userRepository = $userRepository;
$this->router = $router;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
return $request->attributes->get('_route') === 'app_login'
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('login_form')['email'],
'password' => $request->request->get('login_form')['plainPassword'],
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $this->userRepository->findOneBy(['email' => $credentials['email']]);
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
//Redirects to homepage after login
return new RedirectResponse($this->router->generate('app_homepage'));
}
protected function getLoginUrl()
{
return $this->router->generate('app_login');
}
В файле security.yml под провайдерами у меня есть
in_memory:
memory:
users:
[email protected]:
field: email
password: $2y$13$st6a8CcDt/X2ng.8b2brEeP0C/MiXSr78er4lTlnWIKzcCJv2ZF8y
roles: 'ROLE_ADMIN'
Ваш Аутентификатор запрашивает UserRepository. У вас может быть собственный репозиторий, который взаимодействует с InMemoryUserProvider, но я бы порекомендовал вам, когда вы заставите пользователя в вашем аутентификаторе использовать также переданный UserProviderInterface. Это будет использоваться в зависимости от того, какой провайдер настроен как в разделе провайдеров, так и в разделе, который вы выбрали в брандмауэре. Если у вас есть только 1 UserProvider (ваш провайдер in_memory), который будет автоматически использоваться в вашем брандмауэре.
В вашем security.yaml вам не нужно указывать field: email
поскольку поле формы сопоставляется с именем пользователя вашим аутентификатором, а InMemoryUserProvider не использует эту конфигурацию никоим образом. Это означает, например, ваш getUser()
может выглядеть так:
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUsername($credentials['email']);
}
Остальная часть вашего аутентификатора выглядит хорошо, чтобы работать с этим также. Вы должны быть осторожны в своем приложении, поскольку пользовательский класс, который вы получаете от провайдера, — это не сущность, а пользовательский класс по умолчанию, предоставляемый самой Symfony. Symfony\Component\Security\Core\User\User
,
Раздел ваших провайдеров в security.yaml
должно выглядеть как в документации (каждый пользователь содержит только password
а также roles
) и в вашем брандмауэре вы можете ссылаться на провайдера, используя provider: 'in_memory'
(или любое другое имя, которое вы выбрали для провайдера).
Других решений пока нет …