Мне нужно добавить дополнительное поле к json логину, в настоящее время я могу POST
a _username
и _password
на мою login_check
конечную точку, но мне также нужно отправить _school_name
так же имя пользователя можно использовать в разных школах.
Я использую json_login (https://symfony.com/doc/current/security/json_login_setup.html) с пакетом lexik jwt. Должен ли я создать собственный контроллер для этого или GuardAuthenticator?
Я пытался расширить AbstractGuardAuthenticator
, и я попробовал AbstractFormLoginAuthenticator
, но они оба не работают для меня. По умолчанию я использовал это:
login:
pattern: ^/api/v1/token
stateless: true
anonymous: true
user_checker: App\Security\UserChecker
json_login:
check_path: /api/v1/token/login
success_handler: lexik_jwt_authentication.handler.authentication_success
failure_handler: lexik_jwt_authentication.handler.authentication_failure
Затем я добавил свой собственный Guard:
login:
pattern: ^/api/v1/token
stateless: true
anonymous: true
user_checker: App\Security\UserChecker
guard:
authenticators:
- App\Security\BaseAuthenticator
<?php
namespace App\Security;
use App\Entity\Client;
use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
class BaseAuthenticator extends AbstractGuardAuthenticator
{
const LOGIN_ROUTE = 'login_check';
private EntityManagerInterface $entityManager;
private UrlGeneratorInterface $urlGenerator;
private CsrfTokenManagerInterface $csrfTokenManager;
private UserPasswordEncoderInterface $passwordEncoder;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
/**
* @param Request $request
* @return bool
*/
public function supports(Request $request)
{
if ($request->attributes->get('_route') !== static::LOGIN_ROUTE) {
return false;
}
if (!$request->isMethod(Request::METHOD_POST)) {
return false;
}
return true;
}
/**
* @param Request $request
* @return mixed
*/
public function getCredentials(Request $request)
{
return [
'client_name' => $request->request->get('client_name'),
'username' => $request->request->get('username'),
'password' => $request->request->get('password')
];
}
/**
* @param mixed $credentials
* @param UserProviderInterface $userProvider
* @return UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
$userRepository = $this->entityManager->getRepository(User::class);
$clientRepository = $this->entityManager->getRepository(Client::class);
$client = $clientRepository->findOneBy([
'name' => $credentials['client_name']
]);
if (!$client instanceof Client) {
throw new CustomUserMessageAuthenticationException('Client not found');
}
$user = $userRepository->findOneBy([
'client_id' => $client->getId(),
'username' => $credentials['username']
]);
if (!$user instanceof User) {
throw new CustomUserMessageAuthenticationException('User not found');
}
return $user;
}
/**
* @param mixed $credentials
* @param UserInterface $user
* @return bool
*/
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
/**
* @param Request $request
* @param TokenInterface $token
* @param string $providerKey
* @return Response|null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey)
{
return null;
}
/**
* @param Request $request
* @param AuthenticationException|null $authException
* @return Response
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$data = [
// you might translate this message
'message' => 'Authentication Required'
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
/**
* @param Request $request
* @param AuthenticationException $exception
* @return JsonResponse
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = [
// you may want to customize or obfuscate the message first
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
];
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
/**
* @return bool
*/
public function supportsRememberMe()
{
return false;
}
}
Спасибо!