Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit48c698a

Browse files
[Security] add "anonymous: lazy" mode to firewalls
1 parent3c7172d commit48c698a

File tree

13 files changed

+238
-6
lines changed

13 files changed

+238
-6
lines changed

‎src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
useSymfony\Component\HttpFoundation\Response;
1818
useSymfony\Component\HttpKernel\DataCollector\DataCollector;
1919
useSymfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
20+
useSymfony\Component\Security\Core\Authentication\Token\AnonymousToken;
2021
useSymfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
2122
useSymfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
2223
useSymfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
@@ -127,7 +128,7 @@ public function collect(Request $request, Response $response, \Exception $except
127128

128129
$logoutUrl =null;
129130
try {
130-
if (null !==$this->logoutUrlGenerator) {
131+
if (null !==$this->logoutUrlGenerator && !$tokeninstanceof AnonymousToken) {
131132
$logoutUrl =$this->logoutUrlGenerator->getLogoutPath();
132133
}
133134
}catch (\Exception$e) {

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/AnonymousFactory.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,12 @@ public function getKey()
5555
publicfunctionaddConfiguration(NodeDefinition$builder)
5656
{
5757
$builder
58+
->beforeNormalization()
59+
->ifTrue(function ($v) {return'lazy' ===$v; })
60+
->then(function ($v) {return ['lazy' =>true]; })
61+
->end()
5862
->children()
63+
->booleanNode('lazy')->defaultFalse()->end()
5964
->scalarNode('secret')->defaultNull()->end()
6065
->end()
6166
;

‎src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@ private function createFirewalls(array $config, ContainerBuilder $container)
243243
list($matcher,$listeners,$exceptionListener,$logoutListener) =$this->createFirewall($container,$name,$firewall,$authenticationProviders,$providerIds,$configId);
244244

245245
$contextId ='security.firewall.map.context.'.$name;
246-
$context =$container->setDefinition($contextId,newChildDefinition('security.firewall.context'));
246+
$context =newChildDefinition($firewall['stateless'] ||empty($firewall['anonymous']['lazy']) ?'security.firewall.context' :'security.firewall.lazy_context');
247+
$context =$container->setDefinition($contextId,$context);
247248
$context
248249
->replaceArgument(0,newIteratorArgument($listeners))
249250
->replaceArgument(1,$exceptionListener)
@@ -409,7 +410,9 @@ private function createFirewall(ContainerBuilder $container, string $id, array $
409410
}
410411

411412
// Access listener
412-
$listeners[] =newReference('security.access_listener');
413+
if ($firewall['stateless'] ||empty($firewall['anonymous']['lazy'])) {
414+
$listeners[] =newReference('security.access_listener');
415+
}
413416

414417
// Exception listener
415418
$exceptionListener =newReference($this->createExceptionListener($container,$firewall,$id,$configuredEntryPoint ?:$defaultEntryPoint,$firewall['stateless']));

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,16 @@
151151
<argument /><!-- FirewallConfig-->
152152
</service>
153153

154+
<serviceid="security.firewall.lazy_context"class="Symfony\Bundle\SecurityBundle\Security\LazyFirewallContext"abstract="true">
155+
<argumenttype="collection" />
156+
<argumenttype="service"id="security.exception_listener" />
157+
<argument /><!-- LogoutListener-->
158+
<argument /><!-- FirewallConfig-->
159+
<argumenttype="service"id="security.access_listener" />
160+
<argumenttype="service"id="security.untracked_token_storage" />
161+
<argumenttype="service"id="security.access_map" />
162+
</service>
163+
154164
<serviceid="security.firewall.config"class="Symfony\Bundle\SecurityBundle\Security\FirewallConfig"abstract="true">
155165
<argument /><!-- name-->
156166
<argument /><!-- user_checker-->
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespaceSymfony\Bundle\SecurityBundle\Security;
13+
14+
useSymfony\Component\HttpKernel\Event\RequestEvent;
15+
useSymfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
16+
useSymfony\Component\Security\Core\Authorization\Voter\AuthenticatedVoter;
17+
useSymfony\Component\Security\Core\Exception\LazyResponseException;
18+
useSymfony\Component\Security\Http\AccessMapInterface;
19+
useSymfony\Component\Security\Http\Event\LazyResponseEvent;
20+
useSymfony\Component\Security\Http\Firewall\AccessListener;
21+
useSymfony\Component\Security\Http\Firewall\ExceptionListener;
22+
useSymfony\Component\Security\Http\Firewall\LogoutListener;
23+
24+
/**
25+
* Lazily calls authentication listeners when actually required by the access listener.
26+
*
27+
* @author Nicolas Grekas <p@tchwork.com>
28+
*/
29+
class LazyFirewallContextextends FirewallContext
30+
{
31+
private$accessListener;
32+
private$tokenStorage;
33+
private$map;
34+
35+
publicfunction__construct(iterable$listeners, ?ExceptionListener$exceptionListener, ?LogoutListener$logoutListener, ?FirewallConfig$config,AccessListener$accessListener,TokenStorage$tokenStorage,AccessMapInterface$map)
36+
{
37+
parent::__construct($listeners,$exceptionListener,$logoutListener,$config);
38+
39+
$this->accessListener =$accessListener;
40+
$this->tokenStorage =$tokenStorage;
41+
$this->map =$map;
42+
}
43+
44+
publicfunctiongetListeners():iterable
45+
{
46+
return [$this];
47+
}
48+
49+
publicfunction__invoke(RequestEvent$event)
50+
{
51+
$this->tokenStorage->setInitializer(function ()use ($event) {
52+
$event =newLazyResponseEvent($event);
53+
foreach (parent::getListeners()as$listener) {
54+
if (\is_callable($listener)) {
55+
$listener($event);
56+
}else {
57+
@trigger_error(sprintf('Calling the "%s::handle()" method from the firewall is deprecated since Symfony 4.3, implement "__invoke()" instead.',\get_class($listener)),E_USER_DEPRECATED);
58+
$listener->handle($event);
59+
}
60+
}
61+
});
62+
63+
try {
64+
[$attributes] =$this->map->getPatterns($event->getRequest());
65+
66+
if ($attributes && [AuthenticatedVoter::IS_AUTHENTICATED_ANONYMOUSLY] !==$attributes) {
67+
($this->accessListener)($event);
68+
}
69+
}catch (LazyResponseException$e) {
70+
$event->setResponse($e->getResponse());
71+
}
72+
}
73+
}

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,6 @@ public function profileAction()
5959

6060
publicfunctionhomepageAction()
6161
{
62-
returnnewResponse('<html><body>Homepage</body></html>');
62+
return(newResponse('<html><body>Homepage</body></html>'))->setPublic();
6363
}
6464
}

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,16 @@ public function testInvalidIpsInAccessControl()
129129
$client->request('GET','/unprotected_resource');
130130
}
131131

132+
publicfunctiontestPublicHomepage()
133+
{
134+
$client =$this->createClient(['test_case' =>'StandardFormLogin','root_config' =>'config.yml']);
135+
$client->request('GET','/en/');
136+
137+
$this->assertEquals(200,$client->getResponse()->getStatusCode(), (string)$client->getResponse());
138+
$this->assertTrue($client->getResponse()->headers->getCacheControlDirective('public'));
139+
$this->assertSame(0,self::$container->get('session')->getUsageIndex());
140+
}
141+
132142
privatefunctionassertAllowed($client,$path)
133143
{
134144
$client->request('GET',$path);

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ security:
2727
check_path:/login_check
2828
default_target_path:/profile
2929
logout:~
30-
anonymous:~
30+
anonymous:lazy
3131

3232
# This firewall is here just to check its the logout functionality
3333
second_area:
@@ -38,6 +38,7 @@ security:
3838
path:/second/logout
3939

4040
access_control:
41+
-{ path: ^/en/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
4142
-{ path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
4243
-{ path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
4344
-{ path: ^/secured-by-one-ip$, ip: 10.10.10.10, roles: IS_AUTHENTICATED_ANONYMOUSLY }

‎src/Symfony/Bundle/SecurityBundle/composer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"symfony/security-core":"^4.4",
2525
"symfony/security-csrf":"^4.2|^5.0",
2626
"symfony/security-guard":"^4.2|^5.0",
27-
"symfony/security-http":"^4.3"
27+
"symfony/security-http":"^4.4"
2828
},
2929
"require-dev": {
3030
"symfony/asset":"^3.4|^4.0|^5.0",

‎src/Symfony/Component/Security/Core/Authentication/Token/Storage/TokenStorage.php‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@
2525
class TokenStorageimplements TokenStorageInterface, ResetInterface
2626
{
2727
private$token;
28+
private$initializer;
2829

2930
/**
3031
* {@inheritdoc}
3132
*/
3233
publicfunctiongetToken()
3334
{
35+
if ($initializer =$this->initializer) {
36+
$this->initializer =null;
37+
$initializer();
38+
}
39+
3440
return$this->token;
3541
}
3642

@@ -43,9 +49,15 @@ public function setToken(TokenInterface $token = null)
4349
@trigger_error(sprintf('Not implementing the "%s::getRoleNames()" method in "%s" is deprecated since Symfony 4.3.', TokenInterface::class,\get_class($token)),E_USER_DEPRECATED);
4450
}
4551

52+
$this->initializer =null;
4653
$this->token =$token;
4754
}
4855

56+
publicfunctionsetInitializer(?callable$initializer):void
57+
{
58+
$this->initializer =$initializer;
59+
}
60+
4961
publicfunctionreset()
5062
{
5163
$this->setToken(null);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp