Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fcd8ff7

Browse filesBrowse files
committed
#27121 reusing AuthorizationChecker into AccessListener
- added deprecation notice about old-signature - added deprecation annotation to properties - added legacy group to old unit tests - added new unit tests - adjusted security.access_listener
1 parent 3af6406 commit fcd8ff7
Copy full SHA for fcd8ff7

File tree

4 files changed

+210
-9
lines changed
Filter options

4 files changed

+210
-9
lines changed

‎src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ CHANGELOG
1919
* Added support for the new Argon2i password encoder
2020
* added `stateless` option to the `switch_user` listener
2121
* deprecated auto picking the first registered provider when no configured provider on a firewall and ambiguous
22+
* `AccessListener` reuses logic of `AuthorizationCheckerInterface`.
23+
`AccessListener::__construct` now accepts `TokenStorageInterface`, `AccessMapInterface` and `AuthorizationCheckerInterface`,
24+
if old signature is used `E_USER_DEPRECATED` will be triggered
2225

2326
3.3.0
2427
-----

‎src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,8 @@
248248
<service id="security.access_listener" class="Symfony\Component\Security\Http\Firewall\AccessListener">
249249
<tag name="monolog.logger" channel="security" />
250250
<argument type="service" id="security.token_storage" />
251-
<argument type="service" id="security.access.decision_manager" />
252251
<argument type="service" id="security.access_map" />
253-
<argument type="service" id="security.authentication.manager" />
252+
<argument type="service" id="security.authorization_checker"/>
254253
</service>
255254
</services>
256255
</container>

‎src/Symfony/Component/Security/Http/Firewall/AccessListener.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Firewall/AccessListener.php
+42-2Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
1616
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1717
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
18+
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
1819
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
1920
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
2021
use Symfony\Component\Security\Http\AccessMapInterface;
@@ -27,15 +28,42 @@
2728
class AccessListener implements ListenerInterface
2829
{
2930
private $tokenStorage;
31+
32+
/**
33+
* @deprecated since Symfony 4.3
34+
*/
3035
private $accessDecisionManager;
3136
private $map;
37+
38+
/**
39+
* @deprecated since Symfony 4.3
40+
*/
3241
private $authManager;
42+
private $authorizationChecker;
3343

34-
public function __construct(TokenStorageInterface $tokenStorage, AccessDecisionManagerInterface $accessDecisionManager, AccessMapInterface $map, AuthenticationManagerInterface $authManager)
44+
/**
45+
* @param AccessDecisionManagerInterface|AccessMapInterface $map
46+
* @param AccessMapInterface|AuthorizationCheckerInterface $authorizationChecker
47+
* @param AuthenticationManagerInterface|null $authManager
48+
*/
49+
public function __construct(TokenStorageInterface $tokenStorage, $map, $authorizationChecker, $authManager = null)
3550
{
51+
if ($authorizationChecker instanceof AccessMapInterface) {
52+
@trigger_error(sprintf('Signature "%s()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.', __METHOD__), E_USER_DEPRECATED);
53+
$accessDecisionManager = $map;
54+
$map = $authorizationChecker;
55+
$authorizationChecker = null;
56+
} elseif (!$authorizationChecker instanceof AuthorizationCheckerInterface) {
57+
throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be an instance of %s or null, %s given.', __METHOD__, AuthorizationCheckerInterface::class, \is_object($authorizationChecker) ? \get_class($authorizationChecker) : \gettype($authorizationChecker)));
58+
} else {
59+
$accessDecisionManager = null;
60+
$authManager = null;
61+
}
62+
3663
$this->tokenStorage = $tokenStorage;
37-
$this->accessDecisionManager = $accessDecisionManager;
3864
$this->map = $map;
65+
$this->authorizationChecker = $authorizationChecker;
66+
$this->accessDecisionManager = $accessDecisionManager;
3967
$this->authManager = $authManager;
4068
}
4169

@@ -59,6 +87,18 @@ public function handle(GetResponseEvent $event)
5987
return;
6088
}
6189

90+
if (null !== $this->authorizationChecker) {
91+
if (!$this->authorizationChecker->isGranted($attributes, $request)) {
92+
$exception = new AccessDeniedException();
93+
$exception->setAttributes($attributes);
94+
$exception->setSubject($request);
95+
96+
throw $exception;
97+
}
98+
99+
return;
100+
}
101+
62102
if (!$token->isAuthenticated()) {
63103
$token = $this->authManager->authenticate($token);
64104
$this->tokenStorage->setToken($token);

‎src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Security/Http/Tests/Firewall/AccessListenerTest.php
+164-5Lines changed: 164 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,37 @@
1717
class AccessListenerTest extends TestCase
1818
{
1919
/**
20+
* @expectedException \InvalidArgumentException
21+
*/
22+
public function testBadConstructorSignature()
23+
{
24+
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
25+
26+
new AccessListener($tokenStorage, null, null, null);
27+
}
28+
29+
/**
30+
* @deprecated
31+
* @group legacy
32+
* @expectedDeprecation Signature "Symfony\Component\Security\Http\Firewall\AccessListener::__construct()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.
33+
*/
34+
public function testOldConstructorSignature()
35+
{
36+
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
37+
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
38+
$accessDecisionManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')->getMock();
39+
$authManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock();
40+
41+
new AccessListener($tokenStorage, $accessDecisionManager, $accessMap, $authManager);
42+
}
43+
44+
/**
45+
* @deprecated
46+
* @group legacy
47+
* @expectedDeprecation Signature "Symfony\Component\Security\Http\Firewall\AccessListener::__construct()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.
2048
* @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
2149
*/
22-
public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
50+
public function testOldHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
2351
{
2452
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
2553

@@ -70,7 +98,56 @@ public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
7098
$listener->handle($event);
7199
}
72100

73-
public function testHandleWhenTheTokenIsNotAuthenticated()
101+
/**
102+
* @expectedException \Symfony\Component\Security\Core\Exception\AccessDeniedException
103+
*/
104+
public function testHandleWhenTheAccessDecisionManagerDecidesToRefuseAccess()
105+
{
106+
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
107+
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
108+
$authorizationChecker = $this->getMockBuilder('\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
109+
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
110+
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
111+
$event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
112+
$attributes = ['foo' => 'bar'];
113+
114+
$tokenStorage
115+
->expects($this->any())
116+
->method('getToken')
117+
->will($this->returnValue($token))
118+
;
119+
120+
$accessMap
121+
->expects($this->any())
122+
->method('getPatterns')
123+
->with($this->equalTo($request))
124+
->will($this->returnValue([$attributes, null]))
125+
;
126+
127+
$authorizationChecker
128+
->expects($this->once())
129+
->method('isGranted')
130+
->with($this->equalTo($attributes), $this->equalTo($request))
131+
->will($this->returnValue(false))
132+
;
133+
134+
$listener = new AccessListener($tokenStorage, $accessMap, $authorizationChecker);
135+
136+
$event
137+
->expects($this->any())
138+
->method('getRequest')
139+
->will($this->returnValue($request))
140+
;
141+
142+
$listener->handle($event);
143+
}
144+
145+
/**
146+
* @deprecated
147+
* @group legacy
148+
* @expectedDeprecation Signature "Symfony\Component\Security\Http\Firewall\AccessListener::__construct()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.
149+
*/
150+
public function testOldHandleWhenTheTokenIsNotAuthenticated()
74151
{
75152
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
76153

@@ -141,7 +218,12 @@ public function testHandleWhenTheTokenIsNotAuthenticated()
141218
$listener->handle($event);
142219
}
143220

144-
public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
221+
/**
222+
* @deprecated
223+
* @group legacy
224+
* @expectedDeprecation Signature "Symfony\Component\Security\Http\Firewall\AccessListener::__construct()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.
225+
*/
226+
public function testOldHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
145227
{
146228
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
147229

@@ -183,10 +265,51 @@ public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
183265
$listener->handle($event);
184266
}
185267

268+
public function testHandleWhenThereIsNoAccessMapEntryMatchingTheRequest()
269+
{
270+
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
271+
$authorizationChecker = $this->getMockBuilder('\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
272+
$event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
273+
$token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock();
274+
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
275+
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
276+
277+
$tokenStorage
278+
->expects($this->any())
279+
->method('getToken')
280+
->will($this->returnValue($token))
281+
;
282+
283+
$event
284+
->expects($this->any())
285+
->method('getRequest')
286+
->will($this->returnValue($request))
287+
;
288+
289+
$accessMap
290+
->expects($this->any())
291+
->method('getPatterns')
292+
->with($this->equalTo($request))
293+
->will($this->returnValue([null, null]))
294+
;
295+
296+
$authorizationChecker
297+
->expects($this->never())
298+
->method('isGranted')
299+
;
300+
301+
$listener = new AccessListener($tokenStorage, $accessMap, $authorizationChecker);
302+
303+
$listener->handle($event);
304+
}
305+
186306
/**
307+
* @deprecated
308+
* @group legacy
309+
* @expectedDeprecation Signature "Symfony\Component\Security\Http\Firewall\AccessListener::__construct()" has changed since Symfony 4.2, now it accepts TokenStorageInterface, AccessMapInterface, AuthorizationCheckerInterface.
187310
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
188311
*/
189-
public function testHandleWhenTheSecurityTokenStorageHasNoToken()
312+
public function testOldHandleWhenTheSecurityTokenStorageHasNoToken()
190313
{
191314
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
192315
$tokenStorage
@@ -195,14 +318,50 @@ public function testHandleWhenTheSecurityTokenStorageHasNoToken()
195318
->will($this->returnValue(null))
196319
;
197320

321+
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->disableOriginalConstructor()->disableOriginalClone()->getMock();
322+
323+
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
324+
$accessMap
325+
->expects($this->any())
326+
->method('getPatterns')
327+
->with($this->equalTo($request))
328+
->will($this->returnValue([['foo' => 'bar'], null]))
329+
;
330+
198331
$listener = new AccessListener(
199332
$tokenStorage,
200333
$this->getMockBuilder('Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface')->getMock(),
201-
$this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock(),
334+
$accessMap,
202335
$this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface')->getMock()
203336
);
204337

205338
$event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
339+
$event
340+
->expects($this->any())
341+
->method('getRequest')
342+
->will($this->returnValue($request))
343+
;
344+
345+
$listener->handle($event);
346+
}
347+
348+
/**
349+
* @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException
350+
*/
351+
public function testHandleWhenTheSecurityTokenStorageHasNoToken()
352+
{
353+
$tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock();
354+
$accessMap = $this->getMockBuilder('Symfony\Component\Security\Http\AccessMapInterface')->getMock();
355+
$authorizationChecker = $this->getMockBuilder('\Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface')->getMock();
356+
$event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
357+
358+
$tokenStorage
359+
->expects($this->any())
360+
->method('getToken')
361+
->will($this->returnValue(null))
362+
;
363+
364+
$listener = new AccessListener($tokenStorage, $accessMap, $authorizationChecker);
206365

207366
$listener->handle($event);
208367
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.