vendor/symfony/security-bundle/DataCollector/SecurityDataCollector.php line 169
<?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\Bundle\SecurityBundle\DataCollector;use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;use Symfony\Bundle\SecurityBundle\Security\FirewallMap;use Symfony\Component\HttpFoundation\Request;use Symfony\Component\HttpFoundation\Response;use Symfony\Component\HttpKernel\DataCollector\DataCollector;use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;use Symfony\Component\Security\Core\Authorization\Voter\TraceableVoter;use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;use Symfony\Component\Security\Http\Firewall\SwitchUserListener;use Symfony\Component\Security\Http\FirewallMapInterface;use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;use Symfony\Component\VarDumper\Caster\ClassStub;use Symfony\Component\VarDumper\Cloner\Data;/*** @author Fabien Potencier <fabien@symfony.com>** @final*/class SecurityDataCollector extends DataCollector implements LateDataCollectorInterface{private ?TokenStorageInterface $tokenStorage;private ?RoleHierarchyInterface $roleHierarchy;private ?LogoutUrlGenerator $logoutUrlGenerator;private ?AccessDecisionManagerInterface $accessDecisionManager;private ?FirewallMapInterface $firewallMap;private ?TraceableFirewallListener $firewall;private bool $hasVarDumper;public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null, FirewallMapInterface $firewallMap = null, TraceableFirewallListener $firewall = null){$this->tokenStorage = $tokenStorage;$this->roleHierarchy = $roleHierarchy;$this->logoutUrlGenerator = $logoutUrlGenerator;$this->accessDecisionManager = $accessDecisionManager;$this->firewallMap = $firewallMap;$this->firewall = $firewall;$this->hasVarDumper = class_exists(ClassStub::class);}public function collect(Request $request, Response $response, \Throwable $exception = null){if (null === $this->tokenStorage) {$this->data = ['enabled' => false,'authenticated' => false,'impersonated' => false,'impersonator_user' => null,'impersonation_exit_path' => null,'token' => null,'token_class' => null,'logout_url' => null,'user' => '','roles' => [],'inherited_roles' => [],'supports_role_hierarchy' => null !== $this->roleHierarchy,];} elseif (null === $token = $this->tokenStorage->getToken()) {$this->data = ['enabled' => true,'authenticated' => false,'impersonated' => false,'impersonator_user' => null,'impersonation_exit_path' => null,'token' => null,'token_class' => null,'logout_url' => null,'user' => '','roles' => [],'inherited_roles' => [],'supports_role_hierarchy' => null !== $this->roleHierarchy,];} else {$inheritedRoles = [];$assignedRoles = $token->getRoleNames();$impersonatorUser = null;if ($token instanceof SwitchUserToken) {$originalToken = $token->getOriginalToken();$impersonatorUser = $originalToken->getUserIdentifier();}if (null !== $this->roleHierarchy) {foreach ($this->roleHierarchy->getReachableRoleNames($assignedRoles) as $role) {if (!\in_array($role, $assignedRoles, true)) {$inheritedRoles[] = $role;}}}$logoutUrl = null;try {$logoutUrl = $this->logoutUrlGenerator?->getLogoutPath();} catch (\Exception) {// fail silently when the logout URL cannot be generated}$this->data = ['enabled' => true,'authenticated' => method_exists($token, 'isAuthenticated') ? $token->isAuthenticated(false) : (bool) $token->getUser(),'impersonated' => null !== $impersonatorUser,'impersonator_user' => $impersonatorUser,'impersonation_exit_path' => null,'token' => $token,'token_class' => $this->hasVarDumper ? new ClassStub($token::class) : $token::class,'logout_url' => $logoutUrl,'user' => $token->getUserIdentifier(),'roles' => $assignedRoles,'inherited_roles' => array_unique($inheritedRoles),'supports_role_hierarchy' => null !== $this->roleHierarchy,];}// collect voters and access decision manager informationif ($this->accessDecisionManager instanceof TraceableAccessDecisionManager) {$this->data['voter_strategy'] = $this->accessDecisionManager->getStrategy();foreach ($this->accessDecisionManager->getVoters() as $voter) {if ($voter instanceof TraceableVoter) {$voter = $voter->getDecoratedVoter();}$this->data['voters'][] = $this->hasVarDumper ? new ClassStub($voter::class) : $voter::class;}// collect voter details$decisionLog = $this->accessDecisionManager->getDecisionLog();foreach ($decisionLog as $key => $log) {$decisionLog[$key]['voter_details'] = [];foreach ($log['voterDetails'] as $voterDetail) {$voterClass = \get_class($voterDetail['voter']);$classData = $this->hasVarDumper ? new ClassStub($voterClass) : $voterClass;$decisionLog[$key]['voter_details'][] = ['class' => $classData,'attributes' => $voterDetail['attributes'], // Only displayed for unanimous strategy'vote' => $voterDetail['vote'],];}unset($decisionLog[$key]['voterDetails']);}$this->data['access_decision_log'] = $decisionLog;} else {$this->data['access_decision_log'] = [];$this->data['voter_strategy'] = 'unknown';$this->data['voters'] = [];}// collect firewall context information$this->data['firewall'] = null;if ($this->firewallMap instanceof FirewallMap) {$firewallConfig = $this->firewallMap->getFirewallConfig($request);if (null !== $firewallConfig) {$this->data['firewall'] = ['name' => $firewallConfig->getName(),'request_matcher' => $firewallConfig->getRequestMatcher(),'security_enabled' => $firewallConfig->isSecurityEnabled(),'stateless' => $firewallConfig->isStateless(),'provider' => $firewallConfig->getProvider(),'context' => $firewallConfig->getContext(),'entry_point' => $firewallConfig->getEntryPoint(),'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(),'access_denied_url' => $firewallConfig->getAccessDeniedUrl(),'user_checker' => $firewallConfig->getUserChecker(),'authenticators' => $firewallConfig->getAuthenticators(),];// generate exit impersonation path from current requestif ($this->data['impersonated'] && null !== $switchUserConfig = $firewallConfig->getSwitchUser()) {$exitPath = $request->getRequestUri();$exitPath .= null === $request->getQueryString() ? '?' : '&';$exitPath .= sprintf('%s=%s', urlencode($switchUserConfig['parameter']), SwitchUserListener::EXIT_VALUE);$this->data['impersonation_exit_path'] = $exitPath;}}}// collect firewall listeners information$this->data['listeners'] = [];if ($this->firewall) {$this->data['listeners'] = $this->firewall->getWrappedListeners();}$this->data['authenticators'] = $this->firewall ? $this->firewall->getAuthenticatorsInfo() : [];}public function reset(){$this->data = [];}public function lateCollect(){$this->data = $this->cloneVar($this->data);}/*** Checks if security is enabled.*/public function isEnabled(): bool{return $this->data['enabled'];}/*** Gets the user.*/public function getUser(): string{return $this->data['user'];}/*** Gets the roles of the user.*/public function getRoles(): array|Data{return $this->data['roles'];}/*** Gets the inherited roles of the user.*/public function getInheritedRoles(): array|Data{return $this->data['inherited_roles'];}/*** Checks if the data contains information about inherited roles. Still the inherited* roles can be an empty array.*/public function supportsRoleHierarchy(): bool{return $this->data['supports_role_hierarchy'];}/*** Checks if the user is authenticated or not.*/public function isAuthenticated(): bool{return $this->data['authenticated'];}public function isImpersonated(): bool{return $this->data['impersonated'];}public function getImpersonatorUser(): ?string{return $this->data['impersonator_user'];}public function getImpersonationExitPath(): ?string{return $this->data['impersonation_exit_path'];}/*** Get the class name of the security token.*/public function getTokenClass(): string|Data|null{return $this->data['token_class'];}/*** Get the full security token class as Data object.*/public function getToken(): ?Data{return $this->data['token'];}/*** Get the logout URL.*/public function getLogoutUrl(): ?string{return $this->data['logout_url'];}/*** Returns the FQCN of the security voters enabled in the application.** @return string[]|Data*/public function getVoters(): array|Data{return $this->data['voters'];}/*** Returns the strategy configured for the security voters.*/public function getVoterStrategy(): string{return $this->data['voter_strategy'];}/*** Returns the log of the security decisions made by the access decision manager.*/public function getAccessDecisionLog(): array|Data{return $this->data['access_decision_log'];}/*** Returns the configuration of the current firewall context.*/public function getFirewall(): array|Data|null{return $this->data['firewall'];}public function getListeners(): array|Data{return $this->data['listeners'];}public function getAuthenticators(): array|Data{return $this->data['authenticators'];}public function getName(): string{return 'security';}}