123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- <?php
- /*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
- namespace Symfony\Component\Security\Http\Authenticator;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpFoundation\Response;
- use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
- use Symfony\Component\HttpKernel\HttpKernelInterface;
- use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
- use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
- use Symfony\Component\Security\Core\Exception\AuthenticationException;
- use Symfony\Component\Security\Core\Exception\AuthenticationServiceException;
- use Symfony\Component\Security\Core\Exception\BadCredentialsException;
- use Symfony\Component\Security\Core\Security;
- use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
- use Symfony\Component\Security\Core\User\UserInterface;
- use Symfony\Component\Security\Core\User\UserProviderInterface;
- use Symfony\Component\Security\Http\Authentication\AuthenticationFailureHandlerInterface;
- use Symfony\Component\Security\Http\Authentication\AuthenticationSuccessHandlerInterface;
- use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
- use Symfony\Component\Security\Http\Authenticator\Passport\Badge\PasswordUpgradeBadge;
- use Symfony\Component\Security\Http\Authenticator\Passport\Badge\RememberMeBadge;
- use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
- use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
- use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
- use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
- use Symfony\Component\Security\Http\HttpUtils;
- use Symfony\Component\Security\Http\ParameterBagUtils;
- /**
- * @author Wouter de Jong <wouter@wouterj.nl>
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @final
- * @experimental in 5.2
- */
- class FormLoginAuthenticator extends AbstractLoginFormAuthenticator
- {
- private $httpUtils;
- private $userProvider;
- private $successHandler;
- private $failureHandler;
- private $options;
- private $httpKernel;
- public function __construct(HttpUtils $httpUtils, UserProviderInterface $userProvider, AuthenticationSuccessHandlerInterface $successHandler, AuthenticationFailureHandlerInterface $failureHandler, array $options)
- {
- $this->httpUtils = $httpUtils;
- $this->userProvider = $userProvider;
- $this->successHandler = $successHandler;
- $this->failureHandler = $failureHandler;
- $this->options = array_merge([
- 'username_parameter' => '_username',
- 'password_parameter' => '_password',
- 'check_path' => '/login_check',
- 'post_only' => true,
- 'enable_csrf' => false,
- 'csrf_parameter' => '_csrf_token',
- 'csrf_token_id' => 'authenticate',
- ], $options);
- }
- protected function getLoginUrl(Request $request): string
- {
- return $this->httpUtils->generateUri($request, $this->options['login_path']);
- }
- public function supports(Request $request): bool
- {
- return ($this->options['post_only'] ? $request->isMethod('POST') : true)
- && $this->httpUtils->checkRequestPath($request, $this->options['check_path']);
- }
- public function authenticate(Request $request): PassportInterface
- {
- $credentials = $this->getCredentials($request);
- $passport = new Passport(new UserBadge($credentials['username'], function ($username) {
- $user = $this->userProvider->loadUserByUsername($username);
- if (!$user instanceof UserInterface) {
- throw new AuthenticationServiceException('The user provider must return a UserInterface object.');
- }
- return $user;
- }), new PasswordCredentials($credentials['password']), [new RememberMeBadge()]);
- if ($this->options['enable_csrf']) {
- $passport->addBadge(new CsrfTokenBadge($this->options['csrf_token_id'], $credentials['csrf_token']));
- }
- if ($this->userProvider instanceof PasswordUpgraderInterface) {
- $passport->addBadge(new PasswordUpgradeBadge($credentials['password'], $this->userProvider));
- }
- return $passport;
- }
- /**
- * @param Passport $passport
- */
- public function createAuthenticatedToken(PassportInterface $passport, string $firewallName): TokenInterface
- {
- return new UsernamePasswordToken($passport->getUser(), null, $firewallName, $passport->getUser()->getRoles());
- }
- public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
- {
- return $this->successHandler->onAuthenticationSuccess($request, $token);
- }
- public function onAuthenticationFailure(Request $request, AuthenticationException $exception): Response
- {
- return $this->failureHandler->onAuthenticationFailure($request, $exception);
- }
- private function getCredentials(Request $request): array
- {
- $credentials = [];
- $credentials['csrf_token'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['csrf_parameter']);
- if ($this->options['post_only']) {
- $credentials['username'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['username_parameter']);
- $credentials['password'] = ParameterBagUtils::getParameterBagValue($request->request, $this->options['password_parameter']) ?? '';
- } else {
- $credentials['username'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['username_parameter']);
- $credentials['password'] = ParameterBagUtils::getRequestParameterValue($request, $this->options['password_parameter']) ?? '';
- }
- if (!\is_string($credentials['username']) && (!\is_object($credentials['username']) || !method_exists($credentials['username'], '__toString'))) {
- throw new BadRequestHttpException(sprintf('The key "%s" must be a string, "%s" given.', $this->options['username_parameter'], \gettype($credentials['username'])));
- }
- $credentials['username'] = trim($credentials['username']);
- if (\strlen($credentials['username']) > Security::MAX_USERNAME_LENGTH) {
- throw new BadCredentialsException('Invalid username.');
- }
- $request->getSession()->set(Security::LAST_USERNAME, $credentials['username']);
- return $credentials;
- }
- public function setHttpKernel(HttpKernelInterface $httpKernel): void
- {
- $this->httpKernel = $httpKernel;
- }
- public function start(Request $request, AuthenticationException $authException = null): Response
- {
- if (!$this->options['use_forward']) {
- return parent::start($request, $authException);
- }
- $subRequest = $this->httpUtils->createRequest($request, $this->options['login_path']);
- $response = $this->httpKernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
- if (200 === $response->getStatusCode()) {
- $response->setStatusCode(401);
- }
- return $response;
- }
- }
|