Я создаю REST Api с Symfony 4.3, и у меня проблема с аутентификацией (пользователь / пароль) с использованием пользовательского провайдера и настраиваемой защиты.
Контекст
Пользователи должны аутентифицировать себя на определенной конечной точке / api / auth / login с именем пользователя / паролем, чтобы получить токен JWT.Все пользователи хранятся в пользовательской таблице со следующей информацией:
- логин
- пароль (НЕ обязательно!)
- метод аутентификации (' LDAP *)1017 * 'или' LOCAL ')
Если метод аутентификации определен в' LOCAL ', мы используем логин / пароль, определенные в таблице пользователя, чтобы аутентифицировать его,Если метод аутентификации определен в «LDAP», я хочу использовать только имя входа (пароль не хранится в базе данных), и я аутентифицирую пользователя по LDAP.
Я создал собственного провайдера пользователя для управленияМой пользовательский класс и я создали собственный Аутентификатор Guard для управления двумя методами аутентификации:
class MyUserAuthenticator extends AbstractGuardAuthenticator
{
private $em;
private $logger;
private $userRepository;
public function __construct(EntityManagerInterface $em, TUserRepository $userRepository)
{
$this->em = $em;
$this->userRepository = $userRepository;
}
public function getCredentials(Request $request)
{
$this->logger->info('[UserAuthenticator] getCredentials()');
$data = json_decode($request->getContent(), true);
if(isset($data['username']) && isset($data['password'])) {
$credentials = [
'username' => $data['username'],
'password' => $data['password'],
];
return $credentials;
} else {
throw new BadCredentialsException('username or/and password missing in login request.');
}
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$this->logger->info('[UserAuthenticator] getUser()');
return $this->userRepository->find($credentials['username']);
}
public function checkCredentials($credentials, UserInterface $user)
{
if($user){
$mode = $user->getAuthMethod();
switch($mode) {
case 'LDAP':
// CHECK ON LDAP
break;
case 'LOCAL':
// CHECK password with the User Provider
// if($user->getPassword() == credentials['password']) { return true; } else { return false; }
break;
default:
return false;
break;
}
}
// return true to cause authentication success
return false;
}
}
Проблема
checkCredentials () моего настраиваемого средства проверки подлинности работает отлично, он возвращает TRUE, и я прошел проверку подлинности с помощью защиты (проверка подлинности Guard успешно выполнена в файле журнала).Но после этого кажется, что есть другой дескриптор процесса аутентификации Symfony, который проверяет пароль, и, в конце концов, аутентификация не проходит, если я использую метод аутентификации LDAP (без пароля в базе данных):
[2019-09-27 17:02:55] security.INFO: Ошибка аутентификации.{"исключение": "[объект] (Symfony \ Component \ Security \ Core \ Exception \ BadCredentialsException (код: 0): неверные учетные данные. на /var/www/my.api/vendor/symfony/security-core/Authentication/Provider / UserAuthenticationProvider.php: 85, Symfony \ Component \ Security \ Core \ Exception \ BadCredentialsException (код: 0): неверный представленный пароль. /Var/www/my.api/vendor/symfony/security-core/Authentication/Provider/DaoAuthenticationProvider.php:59) "} []
Я не понимаю, почему проверяется пароль, я справедливо решил создать свою собственную защиту аутентификатора для реализации пользовательского пароляуправление ...
Файл журнала:
[2019-09-27 17:02:55] request.INFO: Matched route "api_auth_login". {"route":"api_auth_login","route_parameters":{"_route":"api_auth_login"},"request_uri":"https://my.api/api/auth/login","method":"POST"} []
[2019-09-27 17:02:55] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"api_login","authenticators":1} []
[2019-09-27 17:02:55] security.DEBUG: Checking support on guard authenticator. {"firewall_key":"api_login","authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] security.DEBUG: Calling getCredentials() on guard authenticator. {"firewall_key":"api_login","authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] app.INFO: [UserAuthenticator] getCredentials() [] []
[2019-09-27 17:02:55] security.DEBUG: Passing guard token information to the GuardAuthenticationProvider {"firewall_key":"api_login","authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] app.INFO: [UserAuthenticator] getUser() [] []
[2019-09-27 17:02:55] doctrine.DEBUG: SELECT [.......] WHERE t0.USERID = ? ["THEUSER"] []
[2019-09-27 17:02:55] app.INFO: [UserAuthenticator] checkCredentials() [] []
[2019-09-27 17:02:55] security.INFO: Guard authentication successful! {"token":"[object] (Symfony\\Component\\Security\\Guard\\Token\\PostAuthenticationGuardToken: PostAuthenticationGuardToken(user=\"THEUSER\", authenticated=true, roles=\"SUPERVISER\"))","authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] security.DEBUG: Guard authenticator set no success response: request continues. {"authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] security.DEBUG: Remember me skipped: it is not configured for the firewall. {"authenticator":"App\\Security\\UserAuthenticator"} []
[2019-09-27 17:02:55] app.INFO: loadUserByUsername() [] []
[2019-09-27 17:02:55] security.INFO: Authentication request failed. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException(code: 0): Bad credentials. at /var/www/my.api/vendor/symfony/security-core/Authentication/Provider/UserAuthenticationProvider.php:85, Symfony\\Component\\Security\\Core\\Exception\\BadCredentialsException(code: 0): The presented password is invalid. at /var/www/my.api/vendor/symfony/security-core/Authentication/Provider/DaoAuthenticationProvider.php:59)"} []