发布于 2015-08-27 16:45:00 | 205 次阅读 | 评论: 0 | 来源: 网络整理
When any of the authentication providers (see Authentication Providers) has verified the still-unauthenticated token, an authenticated token will be returned. The authentication listener should set this token directly in the TokenStorageInterface
using its setToken()
method.
From then on, the user is authenticated, i.e. identified. Now, other parts of the application can use the token to decide whether or not the user may request a certain URI, or modify a certain object. This decision will be made by an instance of AccessDecisionManagerInterface
.
An authorization decision will always be based on a few things:
For instance, the token’s getRoles()
method may be used to retrieve the roles of the current user (e.g. ROLE_SUPER_ADMIN
), or a decision may be based on the class of the token.
Each attribute stands for a certain right the user should have, e.g. ROLE_ADMIN
to make sure the user is an administrator.
Any object for which access control needs to be checked, like an article or a comment object.
2.6 新版功能: The TokenStorageInterface
was introduced in Symfony 2.6. Prior, you had to use the setToken()
method of the SecurityContextInterface
.
Since deciding whether or not a user is authorized to perform a certain action can be a complicated process, the standard AccessDecisionManager
itself depends on multiple voters, and makes a final verdict based on all the votes (either positive, negative or neutral) it has received. It recognizes several strategies:
affirmative
(default)consensus
unanimous
use SymfonyComponentSecurityCoreAuthorizationAccessDecisionManager; // instances of SymfonyComponentSecurityCoreAuthorizationVoterVoterInterface $voters = array(...); // one of "affirmative", "consensus", "unanimous" $strategy = ...; // whether or not to grant access when all voters abstain $allowIfAllAbstainDecisions = ...; // whether or not to grant access when there is no majority (applies only to the "consensus" strategy) $allowIfEqualGrantedDeniedDecisions = ...; $accessDecisionManager = new AccessDecisionManager( $voters, $strategy, $allowIfAllAbstainDecisions, $allowIfEqualGrantedDeniedDecisions );
参见
You can change the default strategy in the configuration.
Voters are instances of VoterInterface
, which means they have to implement a few methods which allows the decision manager to use them:
supportsAttribute($attribute)
supportsClass($class)
vote(TokenInterface $token, $object, array $attributes)
VoterInterface
, i.e. VoterInterface::ACCESS_GRANTED
, VoterInterface::ACCESS_DENIED
or VoterInterface::ACCESS_ABSTAIN
;The Security component contains some standard voters which cover many use cases:
The AuthenticatedVoter
voter supports the attributes IS_AUTHENTICATED_FULLY
, IS_AUTHENTICATED_REMEMBERED
, and IS_AUTHENTICATED_ANONYMOUSLY
and grants access based on the current level of authentication, i.e. is the user fully authenticated, or only based on a “remember-me” cookie, or even authenticated anonymously?
use SymfonyComponentSecurityCoreAuthenticationAuthenticationTrustResolver; $anonymousClass = 'SymfonyComponentSecurityCoreAuthenticationTokenAnonymousToken'; $rememberMeClass = 'SymfonyComponentSecurityCoreAuthenticationTokenRememberMeToken'; $trustResolver = new AuthenticationTrustResolver($anonymousClass, $rememberMeClass); $authenticatedVoter = new AuthenticatedVoter($trustResolver); // instance of SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface $token = ...; // any object $object = ...; $vote = $authenticatedVoter->vote($token, $object, array('IS_AUTHENTICATED_FULLY');
The RoleVoter
supports attributes starting with ROLE_
and grants access to the user when the required ROLE_*
attributes can all be found in the array of roles returned by the token’s getRoles()
method:
use SymfonyComponentSecurityCoreAuthorizationVoterRoleVoter; $roleVoter = new RoleVoter('ROLE_'); $roleVoter->vote($token, $object, array('ROLE_ADMIN'));
The RoleHierarchyVoter
extends RoleVoter
and provides some additional functionality: it knows how to handle a hierarchy of roles. For instance, a ROLE_SUPER_ADMIN
role may have subroles ROLE_ADMIN
and ROLE_USER
, so that when a certain object requires the user to have the ROLE_ADMIN
role, it grants access to users who in fact have the ROLE_ADMIN
role, but also to users having the ROLE_SUPER_ADMIN
role:
use SymfonyComponentSecurityCoreAuthorizationVoterRoleHierarchyVoter; use SymfonyComponentSecurityCoreRoleRoleHierarchy; $hierarchy = array( 'ROLE_SUPER_ADMIN' => array('ROLE_ADMIN', 'ROLE_USER'), ); $roleHierarchy = new RoleHierarchy($hierarchy); $roleHierarchyVoter = new RoleHierarchyVoter($roleHierarchy);
注解
When you make your own voter, you may of course use its constructor to inject any dependencies it needs to come to a decision.
Roles are objects that give expression to a certain right the user has. The only requirement is that they implement RoleInterface
, which means they should also have a getRole()
method that returns a string representation of the role itself. The default Role
simply returns its first constructor argument:
use SymfonyComponentSecurityCoreRoleRole; $role = new Role('ROLE_ADMIN'); // will echo 'ROLE_ADMIN' echo $role->getRole();
注解
Most authentication tokens extend from AbstractToken
, which means that the roles given to its constructor will be automatically converted from strings to these simple Role
objects.
The access decision manager can be used at any point in a request to decide whether or not the current user is entitled to access a given resource. One optional, but useful, method for restricting access based on a URL pattern is the AccessListener
, which is one of the firewall listeners (see Firewall Listeners) that is triggered for each request matching the firewall map (see A Firewall for HTTP Requests).
It uses an access map (which should be an instance of AccessMapInterface
) which contains request matchers and a corresponding set of attributes that are required for the current user to get access to the application:
use SymfonyComponentSecurityHttpAccessMap; use SymfonyComponentHttpFoundationRequestMatcher; use SymfonyComponentSecurityHttpFirewallAccessListener; $accessMap = new AccessMap(); $requestMatcher = new RequestMatcher('^/admin'); $accessMap->add($requestMatcher, array('ROLE_ADMIN')); $accessListener = new AccessListener( $securityContext, $accessDecisionManager, $accessMap, $authenticationManager );
The access decision manager is also available to other parts of the application via the isGranted()
method of the AuthorizationChecker
. A call to this method will directly delegate the question to the access decision manager:
use SymfonyComponentSecurityCoreAuthorizationAuthorizationChecker; use SymfonyComponentSecurityCoreExceptionAccessDeniedException; $authorizationChecker = new AuthorizationChecker( $tokenStorage, $authenticationManager, $accessDecisionManager ); if (!$authorizationChecker->isGranted('ROLE_ADMIN')) { throw new AccessDeniedException(); }