8000 use the authorization checker to test for roles · symfony/symfony@246705f · GitHub
[go: up one dir, main page]

Skip to content

Commit 246705f

Browse files
committed
use the authorization checker to test for roles
1 parent 32c0172 commit 246705f

File tree

5 files changed

+84
-2
lines changed

5 files changed

+84
-2
lines changed

src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
<service id="security.access.expression_voter" class="%security.access.expression_voter.class%" public="false">
137137
<argument type="service" id="security.expression_language" />
138138
<argument type="service" id="security.authentication.trust_resolver" />
139+
<argument type="service" id="security.authorization_checker" />
139140
<argument type="service" id="security.role_hierarchy" on-invalid="null" />
140141
<tag name="security.voter" priority="245" />
141142
</service>

src/Symfony/Bundle/SecurityBundle/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"require": {
1919
"php": ">=5.3.9",
2020
"ext-xml": "*",
21-
"symfony/security": "^2.8.45|^3.4.15",
21+
"symfony/security": "^2.8.48|^3.4.19",
2222
"symfony/security-acl": "~2.7|~3.0.0",
2323
"symfony/http-kernel": "~2.7|~3.0.0",
2424
"symfony/polyfill-php70": "~1.0"

src/Symfony/Component/Security/Core/Authorization/ExpressionLanguageProvider.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,16 @@ public function getFunctions()
4949
}),
5050

5151
new ExpressionFunction('has_role', function ($role) {
52+
if (isset($variables['auth_checker'])) {
53+
return sprintf('$token && $auth_checker->isGranted(%s)', $role);
54+
}
55+
5256
return sprintf('in_array(%s, $roles)', $role);
5357
}, function (array $variables, $role) {
58+
if (isset($variables['auth_checker'])) {
59+
return $variables['token'] && $variables['auth_checker']->isGranted($role);
60+
}
61+
5462
return \in_array($role, $variables['roles']);
5563
}),
5664
);

src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use Symfony\Component\HttpFoundation\Request;
1717
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
1818
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
19+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
1920
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
2021
use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
2122

@@ -28,13 +29,25 @@ class ExpressionVoter implements VoterInterface
2829
{
2930
private $expressionLanguage;
3031
private $trustResolver;
32+
private $authChecker;
3133
private $roleHierarchy;
3234

33-
public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null)
35+
/**
36+
* @param AuthorizationCheckerInterface $authChecker
37+
*/
38+
public function __construct(ExpressionLanguage $expressionLanguage, AuthenticationTrustResolverInterface $trustResolver, $authChecker = null, RoleHierarchyInterface $roleHierarchy = null)
3439
{
40+
if ($authChecker instanceof $roleHierarchy) {
41+
$roleHierarchy = $authChecker;
42+
$authChecker = null;
43+
} elseif (n B41A ull !== $authChecker && !$authChecker instanceof AuthorizationCheckerInterface) {
44+
throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be an instance of Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface or null, %s given.', __METHOD__, is_object($authChecker) ? get_class($authChecker) : gettype($authChecker)));
45+
}
46+
3547
$this->expressionLanguage = $expressionLanguage;
3648
$this->trustResolver = $trustResolver;
3749
$this->roleHierarchy = $roleHierarchy;
50+
$this->authChecker = $authChecker;
3851
}
3952

4053
public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
@@ -107,6 +120,10 @@ private function getVariables(TokenInterface $token, $object)
107120
$variables['request'] = $object;
108121
}
109122

123+
if (null !== $this->authChecker) {
124+
$variables['auth_checker'] = $this->authChecker;
125+
}
126+
110127
return $variables;
111128
}
112129
}

src/Symfony/Component/Security/Core/Tests/Authorization/ExpressionLanguageTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@
1515
use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver;
1616
use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken;
1717
use Symfony\Component\Security\Core\Authentication\Token\RememberMeToken;
18+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
1819
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
20+
use Symfony\Component\Security\Core\Authorization\AccessDecisionManager;
21+
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;
1922
use Symfony\Component\Security\Core\Authorization\ExpressionLanguage;
23+
use Symfony\Component\Security\Core\Authorization\Voter\RoleVoter;
2024
use Symfony\Component\Security\Core\User\User;
2125

2226
class ExpressionLanguageTest extends TestCase
@@ -39,6 +43,29 @@ public function testIsAuthenticated($token, $expression, $result, array $roles =
3943
$this->assertEquals($result, $expressionLanguage->evaluate($expression, $context));
4044
}
4145

46+
/**
47+
* @dataProvider provider
48+
*/
49+
public function testIsAuthenticatedWithAuthorizationChecker($token, $expression, $result, array $roles = array())
50+
{
51+
$anonymousTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\AnonymousToken';
52+
$rememberMeTokenClass = 'Symfony\\Component\\Security\\Core\\Authentication\\Token\\RememberMeToken';
53+
$expressionLanguage = new ExpressionLanguage();
54+
$trustResolver = new AuthenticationTrustResolver($anonymousTokenClass, $rememberMeTokenClass);
55+
56+
$tokenStorage = new TokenStorage();
57+
$tokenStorage->setToken($token);
58+
$authorizationChecker = new AuthorizationChecker($tokenStorage, $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock(), new AccessDecisionManager(array(new RoleVoter())));
59+
60+
$context = array();
61+
$context['auth_checker'] = $authorizationChecker;
62+
$context['trust_resolver'] = $trustResolver;
63+
$context['token'] = $token;
64+
$context['roles'] = $roles;
65+
66+
$this->assertSame($result, $expressionLanguage->evaluate($expression, $context));
67+
}
68+
4269
public function provider()
4370
{
4471
$roles = array('ROLE_USER', 'ROLE_ADMIN');
@@ -77,4 +104,33 @@ public function provider()
77104
array($usernamePasswordToken, "has_role('ROLE_USER')", true, $roles),
78105
);
79106
}
107+
108+
public function testHasRoleTriggersTokenAuthentication()
109+
{
110+
$token = new UsernamePasswordToken('username', 'password', 'provider', array('ROLE_ADMIN'));
111+
$refreshedToken = new UsernamePasswordToken('username', 'password', 'provider', array('ROLE_USER'));
112+
113+
$tokenStorage = new TokenStorage();
114+
$tokenStorage->setToken($token);
115+
116+
$authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock();
117+
$authenticationManager->method('authenticate')->willReturn($refreshedToken);
118+
119+
$authorizationChecker = new AuthorizationChecker($tokenStorage, $authenticationManager, new AccessDecisionManager(array(new RoleVoter())), true);
120+
121+
$context = array(
122+
'auth_checker' => $authorizationChecker,
123+
'trust_resolver' => $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface')->getMock(),
124+
'token' => $token,
125+
'roles' => array('ROLE_ADMIN'),
126+
);
127+
$expressionLanguage = new ExpressionLanguage();
128+
129+
$this->assertFalse($expressionLanguage->evaluate('has_role("ROLE_ADMIN")', array(
130+
'auth_checker' => $authorizationChecker,
131+
'trust_resolver' => $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface')->getMock(),
132+
'token' => $token,
133+
'roles' => array('ROLE_ADMIN'),
134+
)));
135+
}
80136
}

0 commit comments

Comments
 (0)
0