Symfony安全json_登录添加自定义字段/验证器控制器

Symfony安全json_登录添加自定义字段/验证器控制器,symfony,symfony4,symfony-security,symfony5,lexikjwtauthbundle,Symfony,Symfony4,Symfony Security,Symfony5,Lexikjwtauthbundle,我需要在json登录中添加一个额外字段,目前我可以将用户名和密码发布到我的登录检查端点,但我还需要发送学校名称,以便在不同的学校使用相同的用户名 我将json_login()与lexik jwt捆绑包一起使用。我应该为此创建自定义控制器还是创建GuardAuthenticator 我尝试了扩展AbstractGuardAuthenticator,我尝试了AbstractFormLoginAuthenticator,但它们都不适合我。默认情况下,我使用的是: login: pa

我需要在json登录中添加一个额外字段,目前我可以
用户名和
密码发布到我的
登录检查
端点,但我还需要发送
学校名称
,以便在不同的学校使用相同的用户名

我将json_login()与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
然后我添加了我的自定义保护:

    login:
      pattern:  ^/api/v1/token
      stateless: true
      anonymous: true
      user_checker: App\Security\UserChecker
      guard:
        authenticators:
          - App\Security\BaseAuthenticator

您需要扩展发送的JSON。在验证器中,您可以从请求($request)中获取有关学校的信息并进行处理。您好,您找到解决方案了吗。我遇到了同样的问题,但我认为不可能在json_登录选项上创建自定义验证器,因为它已经创建了自定义验证器:
vendor/symfony/security bundle/DependencyInjection/security/Factory/JsonLoginFactory.php
@createAuthenticator()
。但是我不确定。你需要扩展你发送的JSON。在验证器中,您可以从请求($request)中获取有关学校的信息并进行处理。您好,您找到解决方案了吗。我遇到了同样的问题,但我认为不可能在json_登录选项上创建自定义验证器,因为它已经创建了自定义验证器:
vendor/symfony/security bundle/DependencyInjection/security/Factory/JsonLoginFactory.php
@createAuthenticator()
。但我不确定。
<?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;
    }
}