* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\Security\Http\Firewall; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Http\Event\SwitchUserEvent; use Symfony\Component\Security\Http\SecurityEvents; use Symfony\Component\EventDispatcher\EventDispatcherInterface; /** * SwitchUserListener allows a user to impersonate another one temporarily * (like the Unix su command). * * @author Fabien Potencier */ class SwitchUserListener implements ListenerInterface { const EXIT_VALUE = '_exit'; private $tokenStorage; private $provider; private $userChecker; private $providerKey; private $accessDecisionManager; private $usernameParameter; private $role; private $logger; private $dispatcher; private $stateless; public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null, $stateless = false) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } $this->tokenStorage = $tokenStorage; $this->provider = $provider; $this->userChecker = $userChecker; $this->providerKey = $providerKey; $this->accessDecisionManager = $accessDecisionManager; $this->usernameParameter = $usernameParameter; $this->role = $role; $this->logger = $logger; $this->dispatcher = $dispatcher; $this->stateless = $stateless; } /** * Handles the switch to another user. * * @throws \LogicException if switching to a user failed */ public function handle(GetResponseEvent $event) { $request = $event->getRequest(); $username = $request->get($this->usernameParameter) ?: $request->headers->get($this->usernameParameter); if (!$username) { return; } if (self::EXIT_VALUE === $username) { $this->tokenStorage->setToken($this->attemptExitUser($request)); } else { try { $this->tokenStorage->setToken($this->attemptSwitchUser($request, $username)); } catch (AuthenticationException $e) { throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage())); } } if (!$this->stateless) { $request->query->remove($this->usernameParameter); $request->server->set('QUERY_STRING', http_build_query($request->query->all(), '', '&')); $response = new RedirectResponse($request->getUri(), 302); $event->setResponse($response); } } /** * Attempts to switch to another user. * * @param Request $request A Request instance * @param string $username * * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise * * @throws \LogicException * @throws AccessDeniedException */ private function attemptSwitchUser(Request $request, $username) { $token = $this->tokenStorage->getToken(); $originalToken = $this->getOriginalToken($token); if (false !== $originalToken) { if ($token->getUsername() === $username) { return $token; } throw new \LogicException(sprintf('You are already switched to "%s" user.', $token->getUsername())); } if (false === $this->accessDecisionManager->decide($token, array($this->role))) { $exception = new AccessDeniedException(); $exception->setAttributes($this->role); throw $exception; } if (null !== $this->logger) { $this->logger->info('Attempting to switch to user.', array('username' => $username)); } $user = $this->provider->loadUserByUsername($username); $this->userChecker->checkPostAuth($user); $roles = $user->getRoles(); $roles[] = new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $this->tokenStorage->getToken()); $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); if (null !== $this->dispatcher) { $switchEvent = new SwitchUserEvent($request, $token->getUser(), $token); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); // use the token from the event in case any listeners have replaced it. $token = $switchEvent->getToken(); } return $token; } /** * Attempts to exit from an already switched user. * * @return TokenInterface The original TokenInterface instance * * @throws AuthenticationCredentialsNotFoundException */ private function attemptExitUser(Request $request) { if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) { $user = $this->provider->refreshUser($original->getUser()); $switchEvent = new SwitchUserEvent($request, $user, $original); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); $original = $switchEvent->getToken(); } return $original; } /** * Gets the original Token from a switched one. * * @return TokenInterface|false The original TokenInterface instance, false if the current TokenInterface is not switched */ private function getOriginalToken(TokenInterface $token) { foreach ($token->getRoles() as $role) { if ($role instanceof SwitchUserRole) { return $role->getSource(); } } return false; } } __halt_compiler();----SIGNATURE:----eCA+cQ0DE118WO554KyWj7kuRL/lo5Iu+1MMf6Bt+HuHeQgZUS8sHEBssSDYoJ7tChP4U6jxNafF9sOs39tAY/jqZy6DxPaGIsDprambvuaaKRt/+Xj4okK9aNW7IyfUcAU4mQqT3gg+5PdNkLL1WGSLUooV1vdaxhp1uUXbpIF2qTx9a+RTuYk2cRuU06y2GRqnoOq99Lt3w593e5yUgLHF0TVJODxClAel4b4rSI1b0WVinrfTmHlMlh/sG3TekLCxKADCaT8nSUBDpCigG5cpmLS7BYeoujT1sfxd3ZIpIiaRBQ/eIp+nyFZooHhwLvt+bAIfqpRH8TM9TRGR2lGcm//U3Kmqh1i/h7L96I4LvlL6QFfrfuh4dstDo0NMYy5QsCPFKn5MBedFfaRYDY5bDC6b0F9PseRDxq+qdLg8HRARXutjyP1s+RZ5PuZwSviKGwtpXIKNdxCp5WebgdIhvnD1U4QPgnhW4lnl3OWUxlzn0gXGT1qyxjHUibsLUGFpcY2f1cso4n0Cadxr/M3JCb8zFIF49oBuySFXGK+6DTk6y8C3Ve6lPZiHq1fyJRZfTgsCaSDKIQQgMadn3Ac4Zn+LYqq69tszHj2InSy2+SEhAOqJrxyvduSqJ0PHyQ6aVCsOqhKH7QEOATGw/1H8bvU5W3oJrICV9eVxfG0=----ATTACHMENT:----OTE2MjY4ODk0MDgwMzI5MSAzMTc2NjYwNzQ2OTg4MTExIDMzOTgxOTIzNzEyMDUzNzg=