Actualización

This commit is contained in:
Xes
2025-04-10 12:24:57 +02:00
parent 8969cc929d
commit 45420b6f0d
39760 changed files with 4303286 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
vendor/
composer.lock
phpunit.xml

View File

@@ -0,0 +1,41 @@
<?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\Guard;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
/**
* An optional base class that creates a PostAuthenticationGuardToken for you.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
abstract class AbstractGuardAuthenticator implements GuardAuthenticatorInterface
{
/**
* Shortcut to create a PostAuthenticationGuardToken for you, if you don't really
* care about which authenticated token you're using.
*
* @param UserInterface $user
* @param string $providerKey
*
* @return PostAuthenticationGuardToken
*/
public function createAuthenticatedToken(UserInterface $user, $providerKey)
{
return new PostAuthenticationGuardToken(
$user,
$providerKey,
$user->getRoles()
);
}
}

View File

@@ -0,0 +1,110 @@
<?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\Guard\Authenticator;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
/**
* A base class to make form login authentication easier!
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
abstract class AbstractFormLoginAuthenticator extends AbstractGuardAuthenticator
{
use TargetPathTrait;
/**
* Return the URL to the login page.
*
* @return string
*/
abstract protected function getLoginUrl();
/**
* Override to change what happens after a bad username/password is submitted.
*
* @param Request $request
* @param AuthenticationException $exception
*
* @return RedirectResponse
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
if ($request->getSession() instanceof SessionInterface) {
$request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);
}
$url = $this->getLoginUrl();
return new RedirectResponse($url);
}
/**
* Override to change what happens after successful authentication.
*
* @param Request $request
* @param TokenInterface $token
* @param string $providerKey
*
* @return RedirectResponse
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
@trigger_error(sprintf('The AbstractFormLoginAuthenticator::onAuthenticationSuccess() implementation was deprecated in Symfony 3.1 and will be removed in Symfony 4.0. You should implement this method yourself in %s and remove getDefaultSuccessRedirectUrl().', get_class($this)), E_USER_DEPRECATED);
if (!method_exists($this, 'getDefaultSuccessRedirectUrl')) {
throw new \Exception(sprintf('You must implement onAuthenticationSuccess() or getDefaultSuccessRedirectUrl() in %s.', get_class($this)));
}
$targetPath = null;
// if the user hit a secure page and start() was called, this was
// the URL they were on, and probably where you want to redirect to
if ($request->getSession() instanceof SessionInterface) {
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);
}
if (!$targetPath) {
$targetPath = $this->getDefaultSuccessRedirectUrl();
}
return new RedirectResponse($targetPath);
}
public function supportsRememberMe()
{
return true;
}
/**
* Override to control what happens when the user hits a secure page
* but isn't logged in yet.
*
* @param Request $request
* @param AuthenticationException|null $authException
*
* @return RedirectResponse
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$url = $this->getLoginUrl();
return new RedirectResponse($url);
}
}

View File

@@ -0,0 +1,201 @@
<?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\Guard\Firewall;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
use Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface;
/**
* Authentication listener for the "guard" system.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
class GuardAuthenticationListener implements ListenerInterface
{
private $guardHandler;
private $authenticationManager;
private $providerKey;
private $guardAuthenticators;
private $logger;
private $rememberMeServices;
/**
* @param GuardAuthenticatorHandler $guardHandler The Guard handler
* @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance
* @param string $providerKey The provider (i.e. firewall) key
* @param GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider
* @param LoggerInterface $logger A LoggerInterface instance
*/
public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, $providerKey, array $guardAuthenticators, LoggerInterface $logger = null)
{
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey must not be empty.');
}
$this->guardHandler = $guardHandler;
$this->authenticationManager = $authenticationManager;
$this->providerKey = $providerKey;
$this->guardAuthenticators = $guardAuthenticators;
$this->logger = $logger;
}
/**
* Iterates over each authenticator to see if each wants to authenticate the request.
*
* @param GetResponseEvent $event
*/
public function handle(GetResponseEvent $event)
{
if (null !== $this->logger) {
$this->logger->debug('Checking for guard authentication credentials.', array('firewall_key' => $this->providerKey, 'authenticators' => count($this->guardAuthenticators)));
}
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
// get a key that's unique to *this* guard authenticator
// this MUST be the same as GuardAuthenticationProvider
$uniqueGuardKey = $this->providerKey.'_'.$key;
$this->executeGuardAuthenticator($uniqueGuardKey, $guardAuthenticator, $event);
if ($event->hasResponse()) {
if (null !== $this->logger) {
$this->logger->debug('The "{authenticator}" authenticator set the response. Any later authenticator will not be called', array('authenticator' => get_class($guardAuthenticator)));
}
break;
}
}
}
private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event)
{
$request = $event->getRequest();
try {
if (null !== $this->logger) {
$this->logger->debug('Calling getCredentials() on guard configurator.', array('firewall_key' => $this->providerKey, 'authenticator' => get_class($guardAuthenticator)));
}
// allow the authenticator to fetch authentication info from the request
$credentials = $guardAuthenticator->getCredentials($request);
// allow null to be returned to skip authentication
if (null === $credentials) {
return;
}
// create a token with the unique key, so that the provider knows which authenticator to use
$token = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey);
if (null !== $this->logger) {
$this->logger->debug('Passing guard token information to the GuardAuthenticationProvider', array('firewall_key' => $this->providerKey, 'authenticator' => get_class($guardAuthenticator)));
}
// pass the token into the AuthenticationManager system
// this indirectly calls GuardAuthenticationProvider::authenticate()
$token = $this->authenticationManager->authenticate($token);
if (null !== $this->logger) {
$this->logger->info('Guard authentication successful!', array('token' => $token, 'authenticator' => get_class($guardAuthenticator)));
}
// sets the token on the token storage, etc
$this->guardHandler->authenticateWithToken($token, $request);
} catch (AuthenticationException $e) {
// oh no! Authentication failed!
if (null !== $this->logger) {
$this->logger->info('Guard authentication failed.', array('exception' => $e, 'authenticator' => get_class($guardAuthenticator)));
}
$response = $this->guardHandler->handleAuthenticationFailure($e, $request, $guardAuthenticator, $this->providerKey);
if ($response instanceof Response) {
$event->setResponse($response);
}
return;
}
// success!
$response = $this->guardHandler->handleAuthenticationSuccess($token, $request, $guardAuthenticator, $this->providerKey);
if ($response instanceof Response) {
if (null !== $this->logger) {
$this->logger->debug('Guard authenticator set success response.', array('response' => $response, 'authenticator' => get_class($guardAuthenticator)));
}
$event->setResponse($response);
} else {
if (null !== $this->logger) {
$this->logger->debug('Guard authenticator set no success response: request continues.', array('authenticator' => get_class($guardAuthenticator)));
}
}
// attempt to trigger the remember me functionality
$this->triggerRememberMe($guardAuthenticator, $request, $token, $response);
}
/**
* Should be called if this listener will support remember me.
*
* @param RememberMeServicesInterface $rememberMeServices
*/
public function setRememberMeServices(RememberMeServicesInterface $rememberMeServices)
{
$this->rememberMeServices = $rememberMeServices;
}
/**
* Checks to see if remember me is supported in the authenticator and
* on the firewall. If it is, the RememberMeServicesInterface is notified.
*
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param Request $request
* @param TokenInterface $token
* @param Response $response
*/
private function triggerRememberMe(GuardAuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null)
{
if (null === $this->rememberMeServices) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: it is not configured for the firewall.', array('authenticator' => get_class($guardAuthenticator)));
}
return;
}
if (!$guardAuthenticator->supportsRememberMe()) {
if (null !== $this->logger) {
$this->logger->debug('Remember me skipped: your authenticator does not support it.', array('authenticator' => get_class($guardAuthenticator)));
}
return;
}
if (!$response instanceof Response) {
throw new \LogicException(sprintf(
'%s::onAuthenticationSuccess *must* return a Response if you want to use the remember me functionality. Return a Response, or set remember_me to false under the guard configuration.',
get_class($guardAuthenticator)
));
}
$this->rememberMeServices->loginSuccess($request, $response, $token);
}
}

View File

@@ -0,0 +1,139 @@
<?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\Guard;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
/**
* A utility class that does much of the *work* during the guard authentication process.
*
* By having the logic here instead of the listener, more of the process
* can be called directly (e.g. for manual authentication) or overridden.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
class GuardAuthenticatorHandler
{
private $tokenStorage;
private $dispatcher;
public function __construct(TokenStorageInterface $tokenStorage, EventDispatcherInterface $eventDispatcher = null)
{
$this->tokenStorage = $tokenStorage;
$this->dispatcher = $eventDispatcher;
}
/**
* Authenticates the given token in the system.
*
* @param TokenInterface $token
* @param Request $request
*/
public function authenticateWithToken(TokenInterface $token, Request $request)
{
$this->tokenStorage->setToken($token);
if (null !== $this->dispatcher) {
$loginEvent = new InteractiveLoginEvent($request, $token);
$this->dispatcher->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $loginEvent);
}
}
/**
* Returns the "on success" response for the given GuardAuthenticator.
*
* @param TokenInterface $token
* @param Request $request
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param string $providerKey The provider (i.e. firewall) key
*
* @return null|Response
*/
public function handleAuthenticationSuccess(TokenInterface $token, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey)
{
$response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey);
// check that it's a Response or null
if ($response instanceof Response || null === $response) {
return $response;
}
throw new \UnexpectedValueException(sprintf(
'The %s::onAuthenticationSuccess method must return null or a Response object. You returned %s.',
get_class($guardAuthenticator),
is_object($response) ? get_class($response) : gettype($response)
));
}
/**
* Convenience method for authenticating the user and returning the
* Response *if any* for success.
*
* @param UserInterface $user
* @param Request $request
* @param GuardAuthenticatorInterface $authenticator
* @param string $providerKey The provider (i.e. firewall) key
*
* @return Response|null
*/
public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, GuardAuthenticatorInterface $authenticator, $providerKey)
{
// create an authenticated token for the User
$token = $authenticator->createAuthenticatedToken($user, $providerKey);
// authenticate this in the system
$this->authenticateWithToken($token, $request);
// return the success metric
return $this->handleAuthenticationSuccess($token, $request, $authenticator, $providerKey);
}
/**
* Handles an authentication failure and returns the Response for the
* GuardAuthenticator.
*
* @param AuthenticationException $authenticationException
* @param Request $request
* @param GuardAuthenticatorInterface $guardAuthenticator
* @param string $providerKey The key of the firewall
*
* @return null|Response
*/
public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey)
{
$token = $this->tokenStorage->getToken();
if ($token instanceof PostAuthenticationGuardToken && $providerKey === $token->getProviderKey()) {
$this->tokenStorage->setToken(null);
}
$response = $guardAuthenticator->onAuthenticationFailure($request, $authenticationException);
if ($response instanceof Response || null === $response) {
// returning null is ok, it means they want the request to continue
return $response;
}
throw new \UnexpectedValueException(sprintf(
'The %s::onAuthenticationFailure method must return null or a Response object. You returned %s.',
get_class($guardAuthenticator),
is_object($response) ? get_class($response) : gettype($response)
));
}
}

View File

@@ -0,0 +1,160 @@
<?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\Guard;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface;
/**
* The interface for all "guard" authenticators.
*
* The methods on this interface are called throughout the guard authentication
* process to give you the power to control most parts of the process from
* one location.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface
{
/**
* Get the authentication credentials from the request and return them
* as any type (e.g. an associate array). If you return null, authentication
* will be skipped.
*
* Whatever value you return here will be passed to getUser() and checkCredentials()
*
* For example, for a form login, you might:
*
* if ($request->request->has('_username')) {
* return array(
* 'username' => $request->request->get('_username'),
* 'password' => $request->request->get('_password'),
* );
* } else {
* return;
* }
*
* Or for an API token that's on a header, you might use:
*
* return array('api_key' => $request->headers->get('X-API-TOKEN'));
*
* @param Request $request
*
* @return mixed|null
*/
public function getCredentials(Request $request);
/**
* Return a UserInterface object based on the credentials.
*
* The *credentials* are the return value from getCredentials()
*
* You may throw an AuthenticationException if you wish. If you return
* null, then a UsernameNotFoundException is thrown for you.
*
* @param mixed $credentials
* @param UserProviderInterface $userProvider
*
* @throws AuthenticationException
*
* @return UserInterface|null
*/
public function getUser($credentials, UserProviderInterface $userProvider);
/**
* Returns true if the credentials are valid.
*
* If any value other than true is returned, authentication will
* fail. You may also throw an AuthenticationException if you wish
* to cause authentication to fail.
*
* The *credentials* are the return value from getCredentials()
*
* @param mixed $credentials
* @param UserInterface $user
*
* @return bool
*
* @throws AuthenticationException
*/
public function checkCredentials($credentials, UserInterface $user);
/**
* Create an authenticated token for the given user.
*
* If you don't care about which token class is used or don't really
* understand what a "token" is, you can skip this method by extending
* the AbstractGuardAuthenticator class from your authenticator.
*
* @see AbstractGuardAuthenticator
*
* @param UserInterface $user
* @param string $providerKey The provider (i.e. firewall) key
*
* @return GuardTokenInterface
*/
public function createAuthenticatedToken(UserInterface $user, $providerKey);
/**
* Called when authentication executed, but failed (e.g. wrong username password).
*
* This should return the Response sent back to the user, like a
* RedirectResponse to the login page or a 403 response.
*
* If you return null, the request will continue, but the user will
* not be authenticated. This is probably not what you want to do.
*
* @param Request $request
* @param AuthenticationException $exception
*
* @return Response|null
*/
public function onAuthenticationFailure(Request $request, AuthenticationException $exception);
/**
* Called when authentication executed and was successful!
*
* This should return the Response sent back to the user, like a
* RedirectResponse to the last page they visited.
*
* If you return null, the current request will continue, and the user
* will be authenticated. This makes sense, for example, with an API.
*
* @param Request $request
* @param TokenInterface $token
* @param string $providerKey The provider (i.e. firewall) key
*
* @return Response|null
*/
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey);
/**
* Does this method support remember me cookies?
*
* Remember me cookie will be set if *all* of the following are met:
* A) This method returns true
* B) The remember_me key under your firewall is configured
* C) The "remember me" functionality is activated. This is usually
* done by having a _remember_me checkbox in your form, but
* can be configured by the "always_remember_me" and "remember_me_parameter"
* parameters under the "remember_me" firewall key
*
* @return bool
*/
public function supportsRememberMe();
}

19
vendor/symfony/security/Guard/LICENSE vendored Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2004-2017 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,147 @@
<?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\Guard\Provider;
use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Symfony\Component\Security\Guard\GuardAuthenticatorInterface;
use Symfony\Component\Security\Guard\Token\GuardTokenInterface;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\User\UserCheckerInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationExpiredException;
/**
* Responsible for accepting the PreAuthenticationGuardToken and calling
* the correct authenticator to retrieve the authenticated token.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
class GuardAuthenticationProvider implements AuthenticationProviderInterface
{
/**
* @var GuardAuthenticatorInterface[]
*/
private $guardAuthenticators;
private $userProvider;
private $providerKey;
private $userChecker;
/**
* @param GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener
* @param UserProviderInterface $userProvider The user provider
* @param string $providerKey The provider (i.e. firewall) key
* @param UserCheckerInterface $userChecker
*/
public function __construct(array $guardAuthenticators, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker)
{
$this->guardAuthenticators = $guardAuthenticators;
$this->userProvider = $userProvider;
$this->providerKey = $providerKey;
$this->userChecker = $userChecker;
}
/**
* Finds the correct authenticator for the token and calls it.
*
* @param GuardTokenInterface $token
*
* @return TokenInterface
*/
public function authenticate(TokenInterface $token)
{
if (!$this->supports($token)) {
throw new \InvalidArgumentException('GuardAuthenticationProvider only supports GuardTokenInterface.');
}
if (!$token instanceof PreAuthenticationGuardToken) {
/*
* The listener *only* passes PreAuthenticationGuardToken instances.
* This means that an authenticated token (e.g. PostAuthenticationGuardToken)
* is being passed here, which happens if that token becomes
* "not authenticated" (e.g. happens if the user changes between
* requests). In this case, the user should be logged out, so
* we will return an AnonymousToken to accomplish that.
*/
// this should never happen - but technically, the token is
// authenticated... so it could just be returned
if ($token->isAuthenticated()) {
return $token;
}
// this AccountStatusException causes the user to be logged out
throw new AuthenticationExpiredException();
}
// find the *one* GuardAuthenticator that this token originated from
foreach ($this->guardAuthenticators as $key => $guardAuthenticator) {
// get a key that's unique to *this* guard authenticator
// this MUST be the same as GuardAuthenticationListener
$uniqueGuardKey = $this->providerKey.'_'.$key;
if ($uniqueGuardKey == $token->getGuardProviderKey()) {
return $this->authenticateViaGuard($guardAuthenticator, $token);
}
}
// no matching authenticator found - but there will be multiple GuardAuthenticationProvider
// instances that will be checked if you have multiple firewalls.
}
private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token)
{
// get the user from the GuardAuthenticator
$user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider);
if (null === $user) {
throw new UsernameNotFoundException(sprintf(
'Null returned from %s::getUser()',
get_class($guardAuthenticator)
));
}
if (!$user instanceof UserInterface) {
throw new \UnexpectedValueException(sprintf(
'The %s::getUser() method must return a UserInterface. You returned %s.',
get_class($guardAuthenticator),
is_object($user) ? get_class($user) : gettype($user)
));
}
$this->userChecker->checkPreAuth($user);
if (true !== $guardAuthenticator->checkCredentials($token->getCredentials(), $user)) {
throw new BadCredentialsException(sprintf('Authentication failed because %s::checkCredentials() did not return true.', get_class($guardAuthenticator)));
}
$this->userChecker->checkPostAuth($user);
// turn the UserInterface into a TokenInterface
$authenticatedToken = $guardAuthenticator->createAuthenticatedToken($user, $this->providerKey);
if (!$authenticatedToken instanceof TokenInterface) {
throw new \UnexpectedValueException(sprintf(
'The %s::createAuthenticatedToken() method must return a TokenInterface. You returned %s.',
get_class($guardAuthenticator),
is_object($authenticatedToken) ? get_class($authenticatedToken) : gettype($authenticatedToken)
));
}
return $authenticatedToken;
}
public function supports(TokenInterface $token)
{
return $token instanceof GuardTokenInterface;
}
}

15
vendor/symfony/security/Guard/README.md vendored Normal file
View File

@@ -0,0 +1,15 @@
Security Component - Guard
==========================
The Guard component brings many layers of authentication together, making
it much easier to create complex authentication systems where you have
total control.
Resources
---------
* [Documentation](https://symfony.com/doc/current/components/security/index.html)
* [Contributing](https://symfony.com/doc/current/contributing/index.html)
* [Report issues](https://github.com/symfony/symfony/issues) and
[send Pull Requests](https://github.com/symfony/symfony/pulls)
in the [main Symfony repository](https://github.com/symfony/symfony)

View File

@@ -0,0 +1,222 @@
<?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\Guard\Tests\Authenticator;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
/**
* @author Jean Pasdeloup <jpasdeloup@sedona.fr>
*/
class FormLoginAuthenticatorTest extends TestCase
{
private $requestWithoutSession;
private $requestWithSession;
private $authenticator;
const LOGIN_URL = 'http://login';
const DEFAULT_SUCCESS_URL = 'http://defaultsuccess';
const CUSTOM_SUCCESS_URL = 'http://customsuccess';
public function testAuthenticationFailureWithoutSession()
{
$failureResponse = $this->authenticator->onAuthenticationFailure($this->requestWithoutSession, new AuthenticationException());
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $failureResponse);
$this->assertEquals(self::LOGIN_URL, $failureResponse->getTargetUrl());
}
public function testAuthenticationFailureWithSession()
{
$this->requestWithSession->getSession()
->expects($this->once())
->method('set');
$failureResponse = $this->authenticator->onAuthenticationFailure($this->requestWithSession, new AuthenticationException());
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $failureResponse);
$this->assertEquals(self::LOGIN_URL, $failureResponse->getTargetUrl());
}
/**
* @group legacy
*/
public function testAuthenticationSuccessWithoutSession()
{
$token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface')
->disableOriginalConstructor()
->getMock();
$redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithoutSession, $token, 'providerkey');
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse);
$this->assertEquals(self::DEFAULT_SUCCESS_URL, $redirectResponse->getTargetUrl());
}
/**
* @group legacy
*/
public function testAuthenticationSuccessWithSessionButEmpty()
{
$token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface')
->disableOriginalConstructor()
->getMock();
$this->requestWithSession->getSession()
->expects($this->once())
->method('get')
->will($this->returnValue(null));
$redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithSession, $token, 'providerkey');
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse);
$this->assertEquals(self::DEFAULT_SUCCESS_URL, $redirectResponse->getTargetUrl());
}
/**
* @group legacy
*/
public function testAuthenticationSuccessWithSessionAndTarget()
{
$token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface')
->disableOriginalConstructor()
->getMock();
$this->requestWithSession->getSession()
->expects($this->once())
->method('get')
->will($this->returnValue(self::CUSTOM_SUCCESS_URL));
$redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithSession, $token, 'providerkey');
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse);
$this->assertEquals(self::CUSTOM_SUCCESS_URL, $redirectResponse->getTargetUrl());
}
public function testRememberMe()
{
$doSupport = $this->authenticator->supportsRememberMe();
$this->assertTrue($doSupport);
}
public function testStartWithoutSession()
{
$failureResponse = $this->authenticator->start($this->requestWithoutSession, new AuthenticationException());
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $failureResponse);
$this->assertEquals(self::LOGIN_URL, $failureResponse->getTargetUrl());
}
public function testStartWithSession()
{
$failureResponse = $this->authenticator->start($this->requestWithSession, new AuthenticationException());
$this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $failureResponse);
$this->assertEquals(self::LOGIN_URL, $failureResponse->getTargetUrl());
}
protected function setUp()
{
$this->requestWithoutSession = new Request(array(), array(), array(), array(), array(), array());
$this->requestWithSession = new Request(array(), array(), array(), array(), array(), array());
$session = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\Session\\SessionInterface')
->disableOriginalConstructor()
->getMock();
$this->requestWithSession->setSession($session);
$this->authenticator = new TestFormLoginAuthenticator();
$this->authenticator
->setLoginUrl(self::LOGIN_URL)
->setDefaultSuccessRedirectUrl(self::DEFAULT_SUCCESS_URL)
;
}
protected function tearDown()
{
$this->request = null;
$this->requestWithSession = null;
}
}
class TestFormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
private $loginUrl;
private $defaultSuccessRedirectUrl;
/**
* @param mixed $defaultSuccessRedirectUrl
*
* @return TestFormLoginAuthenticator
*/
public function setDefaultSuccessRedirectUrl($defaultSuccessRedirectUrl)
{
$this->defaultSuccessRedirectUrl = $defaultSuccessRedirectUrl;
return $this;
}
/**
* @param mixed $loginUrl
*
* @return TestFormLoginAuthenticator
*/
public function setLoginUrl($loginUrl)
{
$this->loginUrl = $loginUrl;
return $this;
}
/**
* {@inheritdoc}
*/
protected function getLoginUrl()
{
return $this->loginUrl;
}
/**
* {@inheritdoc}
*/
protected function getDefaultSuccessRedirectUrl()
{
return $this->defaultSuccessRedirectUrl;
}
/**
* {@inheritdoc}
*/
public function getCredentials(Request $request)
{
return 'credentials';
}
/**
* {@inheritdoc}
*/
public function getUser($credentials, UserProviderInterface $userProvider)
{
return $userProvider->loadUserByUsername($credentials);
}
/**
* {@inheritdoc}
*/
public function checkCredentials($credentials, UserInterface $user)
{
return true;
}
}

View File

@@ -0,0 +1,257 @@
<?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\Guard\Tests\Firewall;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener;
use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
/**
* @author Ryan Weaver <weaverryan@gmail.com>
*/
class GuardAuthenticationListenerTest extends TestCase
{
private $authenticationManager;
private $guardAuthenticatorHandler;
private $event;
private $logger;
private $request;
private $rememberMeServices;
public function testHandleSuccess()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$providerKey = 'my_firewall';
$credentials = array('username' => 'weaverryan', 'password' => 'all_your_base');
$authenticator
->expects($this->once())
->method('getCredentials')
->with($this->equalTo($this->request))
->will($this->returnValue($credentials));
// a clone of the token that should be created internally
$uniqueGuardKey = 'my_firewall_0';
$nonAuthedToken = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey);
$this->authenticationManager
->expects($this->once())
->method('authenticate')
->with($this->equalTo($nonAuthedToken))
->will($this->returnValue($authenticateToken));
$this->guardAuthenticatorHandler
->expects($this->once())
->method('authenticateWithToken')
->with($authenticateToken, $this->request);
$this->guardAuthenticatorHandler
->expects($this->once())
->method('handleAuthenticationSuccess')
->with($authenticateToken, $this->request, $authenticator, $providerKey);
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->setRememberMeServices($this->rememberMeServices);
// should never be called - our handleAuthenticationSuccess() does not return a Response
$this->rememberMeServices
->expects($this->never())
->method('loginSuccess');
$listener->handle($this->event);
}
public function testHandleSuccessStopsAfterResponseIsSet()
{
$authenticator1 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticator2 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
// mock the first authenticator to fail, and set a Response
$authenticator1
->expects($this->once())
->method('getCredentials')
->willThrowException(new AuthenticationException());
$this->guardAuthenticatorHandler
->expects($this->once())
->method('handleAuthenticationFailure')
->willReturn(new Response());
// the second authenticator should *never* be called
$authenticator2
->expects($this->never())
->method('getCredentials');
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
'my_firewall',
array($authenticator1, $authenticator2),
$this->logger
);
$listener->handle($this->event);
}
public function testHandleSuccessWithRememberMe()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$providerKey = 'my_firewall_with_rememberme';
$authenticator
->expects($this->once())
->method('getCredentials')
->with($this->equalTo($this->request))
->will($this->returnValue(array('username' => 'anything_not_empty')));
$this->authenticationManager
->expects($this->once())
->method('authenticate')
->will($this->returnValue($authenticateToken));
$successResponse = new Response('Success!');
$this->guardAuthenticatorHandler
->expects($this->once())
->method('handleAuthenticationSuccess')
->will($this->returnValue($successResponse));
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->setRememberMeServices($this->rememberMeServices);
$authenticator->expects($this->once())
->method('supportsRememberMe')
->will($this->returnValue(true));
// should be called - we do have a success Response
$this->rememberMeServices
->expects($this->once())
->method('loginSuccess');
$listener->handle($this->event);
}
public function testHandleCatchesAuthenticationException()
{
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$providerKey = 'my_firewall2';
$authException = new AuthenticationException('Get outta here crazy user with a bad password!');
$authenticator
->expects($this->once())
->method('getCredentials')
->will($this->throwException($authException));
// this is not called
$this->authenticationManager
->expects($this->never())
->method('authenticate');
$this->guardAuthenticatorHandler
->expects($this->once())
->method('handleAuthenticationFailure')
->with($authException, $this->request, $authenticator, $providerKey);
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticator),
$this->logger
);
$listener->handle($this->event);
}
public function testReturnNullToSkipAuth()
{
$authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$providerKey = 'my_firewall3';
$authenticatorA
->expects($this->once())
->method('getCredentials')
->will($this->returnValue(null));
$authenticatorB
->expects($this->once())
->method('getCredentials')
->will($this->returnValue(null));
// this is not called
$this->authenticationManager
->expects($this->never())
->method('authenticate');
$this->guardAuthenticatorHandler
->expects($this->never())
->method('handleAuthenticationSuccess');
$listener = new GuardAuthenticationListener(
$this->guardAuthenticatorHandler,
$this->authenticationManager,
$providerKey,
array($authenticatorA, $authenticatorB),
$this->logger
);
$listener->handle($this->event);
}
protected function setUp()
{
$this->authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager')
->disableOriginalConstructor()
->getMock();
$this->guardAuthenticatorHandler = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorHandler')
->disableOriginalConstructor()
->getMock();
$this->request = new Request(array(), array(), array(), array(), array(), array());
$this->event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
->disableOriginalConstructor()
->setMethods(array('getRequest'))
->getMock();
$this->event
->expects($this->any())
->method('getRequest')
->will($this->returnValue($this->request));
$this->logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
$this->rememberMeServices = $this->getMockBuilder('Symfony\Component\Security\Http\RememberMe\RememberMeServicesInterface')->getMock();
}
protected function tearDown()
{
$this->authenticationManager = null;
$this->guardAuthenticatorHandler = null;
$this->event = null;
$this->logger = null;
$this->request = null;
$this->rememberMeServices = null;
}
}

View File

@@ -0,0 +1,142 @@
<?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\Guard\Tests;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
use Symfony\Component\Security\Http\SecurityEvents;
class GuardAuthenticatorHandlerTest extends TestCase
{
private $tokenStorage;
private $dispatcher;
private $token;
private $request;
private $guardAuthenticator;
public function testAuthenticateWithToken()
{
$this->tokenStorage->expects($this->once())
->method('setToken')
->with($this->token);
$loginEvent = new InteractiveLoginEvent($this->request, $this->token);
$this->dispatcher
->expects($this->once())
->method('dispatch')
->with($this->equalTo(SecurityEvents::INTERACTIVE_LOGIN), $this->equalTo($loginEvent))
;
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
$handler->authenticateWithToken($this->token, $this->request);
}
public function testHandleAuthenticationSuccess()
{
$providerKey = 'my_handleable_firewall';
$response = new Response('Guard all the things!');
$this->guardAuthenticator->expects($this->once())
->method('onAuthenticationSuccess')
->with($this->request, $this->token, $providerKey)
->will($this->returnValue($response));
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
$actualResponse = $handler->handleAuthenticationSuccess($this->token, $this->request, $this->guardAuthenticator, $providerKey);
$this->assertSame($response, $actualResponse);
}
public function testHandleAuthenticationFailure()
{
// setToken() not called - getToken() will return null, so there's nothing to clear
$this->tokenStorage->expects($this->never())
->method('setToken')
->with(null);
$authException = new AuthenticationException('Bad password!');
$response = new Response('Try again, but with the right password!');
$this->guardAuthenticator->expects($this->once())
->method('onAuthenticationFailure')
->with($this->request, $authException)
->will($this->returnValue($response));
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
$actualResponse = $handler->handleAuthenticationFailure($authException, $this->request, $this->guardAuthenticator, 'firewall_provider_key');
$this->assertSame($response, $actualResponse);
}
/**
* @dataProvider getTokenClearingTests
*/
public function testHandleAuthenticationClearsToken($tokenClass, $tokenProviderKey, $actualProviderKey, $shouldTokenBeCleared)
{
$token = $this->getMockBuilder($tokenClass)
->disableOriginalConstructor()
->getMock();
$token->expects($this->any())
->method('getProviderKey')
->will($this->returnValue($tokenProviderKey));
// make the $token be the current token
$this->tokenStorage->expects($this->once())
->method('getToken')
->will($this->returnValue($token));
$this->tokenStorage->expects($shouldTokenBeCleared ? $this->once() : $this->never())
->method('setToken')
->with(null);
$authException = new AuthenticationException('Bad password!');
$response = new Response('Try again, but with the right password!');
$this->guardAuthenticator->expects($this->once())
->method('onAuthenticationFailure')
->with($this->request, $authException)
->will($this->returnValue($response));
$handler = new GuardAuthenticatorHandler($this->tokenStorage, $this->dispatcher);
$actualResponse = $handler->handleAuthenticationFailure($authException, $this->request, $this->guardAuthenticator, $actualProviderKey);
$this->assertSame($response, $actualResponse);
}
public function getTokenClearingTests()
{
$tests = array();
// correct token class and matching firewall => clear the token
$tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'the_firewall_key', true);
$tests[] = array('Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken', 'the_firewall_key', 'different_key', false);
$tests[] = array('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', 'the_firewall_key', 'the_firewall_key', false);
return $tests;
}
protected function setUp()
{
$this->tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
$this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
$this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$this->request = new Request(array(), array(), array(), array(), array(), array());
$this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
}
protected function tearDown()
{
$this->tokenStorage = null;
$this->dispatcher = null;
$this->token = null;
$this->request = null;
$this->guardAuthenticator = null;
}
}

View File

@@ -0,0 +1,151 @@
<?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\Guard\Tests\Provider;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
/**
* @author Ryan Weaver <weaverryan@gmail.com>
*/
class GuardAuthenticationProviderTest extends TestCase
{
private $userProvider;
private $userChecker;
private $preAuthenticationToken;
public function testAuthenticate()
{
$providerKey = 'my_cool_firewall';
$authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticatorC = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
$authenticators = array($authenticatorA, $authenticatorB, $authenticatorC);
// called 2 times - for authenticator A and B (stops on B because of match)
$this->preAuthenticationToken->expects($this->exactly(2))
->method('getGuardProviderKey')
// it will return the "1" index, which will match authenticatorB
->will($this->returnValue('my_cool_firewall_1'));
$enteredCredentials = array(
'username' => '_weaverryan_test_user',
'password' => 'guard_auth_ftw',
);
$this->preAuthenticationToken->expects($this->atLeastOnce())
->method('getCredentials')
->will($this->returnValue($enteredCredentials));
// authenticators A and C are never called
$authenticatorA->expects($this->never())
->method('getUser');
$authenticatorC->expects($this->never())
->method('getUser');
$mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$authenticatorB->expects($this->once())
->method('getUser')
->with($enteredCredentials, $this->userProvider)
->will($this->returnValue($mockedUser));
// checkCredentials is called
$authenticatorB->expects($this->once())
->method('checkCredentials')
->with($enteredCredentials, $mockedUser)
// authentication works!
->will($this->returnValue(true));
$authedToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
$authenticatorB->expects($this->once())
->method('createAuthenticatedToken')
->with($mockedUser, $providerKey)
->will($this->returnValue($authedToken));
// user checker should be called
$this->userChecker->expects($this->once())
->method('checkPreAuth')
->with($mockedUser);
$this->userChecker->expects($this->once())
->method('checkPostAuth')
->with($mockedUser);
$provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, $providerKey, $this->userChecker);
$actualAuthedToken = $provider->authenticate($this->preAuthenticationToken);
$this->assertSame($authedToken, $actualAuthedToken);
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
*/
public function testCheckCredentialsReturningNonTrueFailsAuthentication()
{
$providerKey = 'my_uncool_firewall';
$authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock();
// make sure the authenticator is used
$this->preAuthenticationToken->expects($this->any())
->method('getGuardProviderKey')
// the 0 index, to match the only authenticator
->will($this->returnValue('my_uncool_firewall_0'));
$this->preAuthenticationToken->expects($this->atLeastOnce())
->method('getCredentials')
->will($this->returnValue('non-null-value'));
$mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$authenticator->expects($this->once())
->method('getUser')
->will($this->returnValue($mockedUser));
// checkCredentials is called
$authenticator->expects($this->once())
->method('checkCredentials')
// authentication fails :(
->will($this->returnValue(null));
$provider = new GuardAuthenticationProvider(array($authenticator), $this->userProvider, $providerKey, $this->userChecker);
$provider->authenticate($this->preAuthenticationToken);
}
/**
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationExpiredException
*/
public function testGuardWithNoLongerAuthenticatedTriggersLogout()
{
$providerKey = 'my_firewall_abc';
// create a token and mark it as NOT authenticated anymore
// this mimics what would happen if a user "changed" between request
$mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock();
$token = new PostAuthenticationGuardToken($mockedUser, $providerKey, array('ROLE_USER'));
$token->setAuthenticated(false);
$provider = new GuardAuthenticationProvider(array(), $this->userProvider, $providerKey, $this->userChecker);
$actualToken = $provider->authenticate($token);
}
protected function setUp()
{
$this->userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock();
$this->userChecker = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserCheckerInterface')->getMock();
$this->preAuthenticationToken = $this->getMockBuilder('Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken')
->disableOriginalConstructor()
->getMock();
}
protected function tearDown()
{
$this->userProvider = null;
$this->userChecker = null;
$this->preAuthenticationToken = null;
}
}

View File

@@ -0,0 +1,27 @@
<?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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
/**
* A marker interface that both guard tokens implement.
*
* Any tokens passed to GuardAuthenticationProvider (i.e. any tokens that
* are handled by the guard auth system) must implement this
* interface.
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
interface GuardTokenInterface extends TokenInterface
{
}

View File

@@ -0,0 +1,90 @@
<?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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Role\RoleInterface;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* Used as an "authenticated" token, though it could be set to not-authenticated later.
*
* If you're using Guard authentication, you *must* use a class that implements
* GuardTokenInterface as your authenticated token (like this class).
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface
{
private $providerKey;
/**
* @param UserInterface $user The user!
* @param string $providerKey The provider (firewall) key
* @param RoleInterface[]|string[] $roles An array of roles
*
* @throws \InvalidArgumentException
*/
public function __construct(UserInterface $user, $providerKey, array $roles)
{
parent::__construct($roles);
if (empty($providerKey)) {
throw new \InvalidArgumentException('$providerKey (i.e. firewall key) must not be empty.');
}
$this->setUser($user);
$this->providerKey = $providerKey;
// this token is meant to be used after authentication success, so it is always authenticated
// you could set it as non authenticated later if you need to
parent::setAuthenticated(true);
}
/**
* This is meant to be only an authenticated token, where credentials
* have already been used and are thus cleared.
*
* {@inheritdoc}
*/
public function getCredentials()
{
return array();
}
/**
* Returns the provider (firewall) key.
*
* @return string
*/
public function getProviderKey()
{
return $this->providerKey;
}
/**
* {@inheritdoc}
*/
public function serialize()
{
return serialize(array($this->providerKey, parent::serialize()));
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
{
list($this->providerKey, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
}

View File

@@ -0,0 +1,65 @@
<?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\Guard\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
/**
* The token used by the guard auth system before authentication.
*
* The GuardAuthenticationListener creates this, which is then consumed
* immediately by the GuardAuthenticationProvider. If authentication is
* successful, a different authenticated token is returned
*
* @author Ryan Weaver <ryan@knpuniversity.com>
*/
class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInterface
{
private $credentials;
private $guardProviderKey;
/**
* @param mixed $credentials
* @param string $guardProviderKey Unique key that bind this token to a specific GuardAuthenticatorInterface
*/
public function __construct($credentials, $guardProviderKey)
{
$this->credentials = $credentials;
$this->guardProviderKey = $guardProviderKey;
parent::__construct(array());
// never authenticated
parent::setAuthenticated(false);
}
public function getGuardProviderKey()
{
return $this->guardProviderKey;
}
/**
* Returns the user credentials, which might be an array of anything you
* wanted to put in there (e.g. username, password, favoriteColor).
*
* @return mixed The user credentials
*/
public function getCredentials()
{
return $this->credentials;
}
public function setAuthenticated($authenticated)
{
throw new \LogicException('The PreAuthenticationGuardToken is *never* authenticated.');
}
}

View File

@@ -0,0 +1,38 @@
{
"name": "symfony/security-guard",
"type": "library",
"description": "Symfony Security Component - Guard",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"require": {
"php": ">=5.5.9",
"symfony/security-core": "~2.8|~3.0",
"symfony/security-http": "~3.1"
},
"require-dev": {
"psr/log": "~1.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Security\\Guard\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "3.2-dev"
}
}
}

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="vendor/autoload.php"
failOnRisky="true"
failOnWarning="true"
>
<php>
<ini name="error_reporting" value="-1" />
</php>
<testsuites>
<testsuite name="Symfony Security Component Guard Suite">
<directory>./Tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>