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

Commit3ff46f1

Browse files
committed
Give info about called security listeners in profiler
1 parent7c1febd commit3ff46f1

File tree

11 files changed

+321
-14
lines changed

11 files changed

+321
-14
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ CHANGELOG
55
-----
66

77
*[BC BREAK]`FirewallContext::getListeners()` now returns`\Traversable|array`
8+
* added info about called security listeners in profiler
89

910
3.3.0
1011
-----

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
useSymfony\Component\HttpKernel\DataCollector\DataCollector;
2020
useSymfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface;
2121
useSymfony\Component\Security\Core\Role\RoleInterface;
22+
useSymfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;
2223
useSymfony\Component\Security\Http\Logout\LogoutUrlGenerator;
2324
useSymfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
2425
useSymfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager;
@@ -39,6 +40,7 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
3940
private$logoutUrlGenerator;
4041
private$accessDecisionManager;
4142
private$firewallMap;
43+
private$firewall;
4244
private$hasVarDumper;
4345

4446
/**
@@ -49,14 +51,16 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn
4951
* @param LogoutUrlGenerator|null $logoutUrlGenerator
5052
* @param AccessDecisionManagerInterface|null $accessDecisionManager
5153
* @param FirewallMapInterface|null $firewallMap
54+
* @param TraceableFirewallListener|null $firewall
5255
*/
53-
publicfunction__construct(TokenStorageInterface$tokenStorage =null,RoleHierarchyInterface$roleHierarchy =null,LogoutUrlGenerator$logoutUrlGenerator =null,AccessDecisionManagerInterface$accessDecisionManager =null,FirewallMapInterface$firewallMap =null)
56+
publicfunction__construct(TokenStorageInterface$tokenStorage =null,RoleHierarchyInterface$roleHierarchy =null,LogoutUrlGenerator$logoutUrlGenerator =null,AccessDecisionManagerInterface$accessDecisionManager =null,FirewallMapInterface$firewallMap =null,TraceableFirewallListener$firewall =null)
5457
{
5558
$this->tokenStorage =$tokenStorage;
5659
$this->roleHierarchy =$roleHierarchy;
5760
$this->logoutUrlGenerator =$logoutUrlGenerator;
5861
$this->accessDecisionManager =$accessDecisionManager;
5962
$this->firewallMap =$firewallMap;
63+
$this->firewall =$firewall;
6064
$this->hasVarDumper =class_exists(ClassStub::class);
6165
}
6266

@@ -167,6 +171,12 @@ public function collect(Request $request, Response $response, \Exception $except
167171
);
168172
}
169173
}
174+
175+
// collect firewall listeners information
176+
$this->data['listeners'] =array();
177+
if ($this->firewall) {
178+
$this->data['listeners'] =$this->firewall->getWrappedListeners();
179+
}
170180
}
171181

172182
publicfunctionlateCollect()
@@ -305,6 +315,11 @@ public function getFirewall()
305315
return$this->data['firewall'];
306316
}
307317

318+
publicfunctiongetListeners()
319+
{
320+
return$this->data['listeners'];
321+
}
322+
308323
/**
309324
* {@inheritdoc}
310325
*/
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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\Debug;
13+
14+
useSymfony\Bundle\SecurityBundle\EventListener\FirewallListener;
15+
useSymfony\Component\HttpKernel\Event\GetResponseEvent;
16+
17+
/**
18+
* Firewall collecting called listeners.
19+
*
20+
* @author Robin Chalas <robin.chalas@gmail.com>
21+
*
22+
* @final since version 3.4
23+
*/
24+
class TraceableFirewallListenerextends FirewallListener
25+
{
26+
private$wrappedListeners;
27+
28+
publicfunctiongetWrappedListeners()
29+
{
30+
return$this->wrappedListeners;
31+
}
32+
33+
protectedfunctionhandleRequest(GetResponseEvent$event,$listeners)
34+
{
35+
foreach ($listenersas$listener) {
36+
$wrappedListener =newWrappedListener($listener);
37+
$wrappedListener->handle($event);
38+
$wrappedListener->response =$event->getResponse();
39+
$this->wrappedListeners[] =$wrappedListener->getInfo();
40+
41+
if ($event->hasResponse()) {
42+
break;
43+
}
44+
}
45+
}
46+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
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\Debug;
13+
14+
useSymfony\Component\HttpKernel\Event\GetResponseEvent;
15+
useSymfony\Component\Security\Http\Firewall\ListenerInterface;
16+
useSymfony\Component\VarDumper\Caster\ClassStub;
17+
18+
/**
19+
* Wraps a security listener for calls record.
20+
*
21+
* @author Robin Chalas <robin.chalas@gmail.com>
22+
*
23+
* @final since version 3.4
24+
*/
25+
class WrappedListenerimplements ListenerInterface
26+
{
27+
public$response;
28+
private$listener;
29+
private$time;
30+
private$stub;
31+
privatestatic$hasVarDumper;
32+
33+
publicfunction__construct(ListenerInterface$listener)
34+
{
35+
$this->listener =$listener;
36+
37+
if (null ===self::$hasVarDumper) {
38+
self::$hasVarDumper =class_exists(ClassStub::class);
39+
}
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
publicfunctionhandle(GetResponseEvent$event)
46+
{
47+
$startTime =microtime(true);
48+
$this->listener->handle($event);
49+
$this->time =microtime(true) -$startTime;
50+
}
51+
52+
/**
53+
* Proxies all method calls to the original listener.
54+
*/
55+
publicfunction__call($method,$arguments)
56+
{
57+
returncall_user_func_array(array($this->listener,$method),$arguments);
58+
}
59+
60+
publicfunctiongetWrappedListener()
61+
{
62+
return$this->listener;
63+
}
64+
65+
publicfunctiongetInfo()
66+
{
67+
if (null ===$this->stub) {
68+
$this->stub =self::$hasVarDumper ?newClassStub(get_class($this->listener)) :get_class($this->listener);
69+
}
70+
71+
returnarray(
72+
'response' =>$this->response,
73+
'time' =>$this->time,
74+
'stub' =>$this->stub,
75+
);
76+
}
77+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<argumenttype="service"id="security.logout_url_generator" />
1515
<argumenttype="service"id="security.access.decision_manager" />
1616
<argumenttype="service"id="security.firewall.map" />
17+
<argumenttype="service"id="debug.security.firewall"on-invalid="null" />
1718
</service>
1819
</services>
1920
</container>

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,14 @@
1010
<serviceid="debug.security.access.decision_manager"class="Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager"decorates="security.access.decision_manager">
1111
<argumenttype="service"id="debug.security.access.decision_manager.inner" />
1212
</service>
13+
14+
<serviceid="debug.security.firewall"class="Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener">
15+
<tagname="kernel.event_subscriber" />
16+
<argumenttype="service"id="security.firewall.map" />
17+
<argumenttype="service"id="event_dispatcher" />
18+
<argumenttype="service"id="security.logout_url_generator" />
19+
</service>
20+
21+
<serviceid="security.firewall"alias="debug.security.firewall"public="true" />
1322
</services>
1423
</container>

‎src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@
150150
</div>
151151

152152
{%ifcollector.firewall.security_enabled %}
153+
<h4>Configuration</h4>
154+
153155
<table>
154156
<thead>
155157
<tr>
@@ -188,6 +190,46 @@
188190
</tr>
189191
</tbody>
190192
</table>
193+
194+
<h4>Listeners</h4>
195+
196+
{%ifcollector.listeners|default([])isempty %}
197+
<divclass="empty">
198+
<p>No security listeners have been recorded. Check that debugging is enabled in the kernel.</p>
199+
</div>
200+
{%else %}
201+
<table>
202+
<thead>
203+
<tr>
204+
<th>Listener</th>
205+
<th>Duration</th>
206+
<th>Response</th>
207+
</tr>
208+
</thead>
209+
210+
{%setprevious_event= (collector.listeners|first) %}
211+
{%forlistenerincollector.listeners %}
212+
{%ifloop.firstorlistener!=previous_event %}
213+
{%ifnotloop.first %}
214+
</tbody>
215+
{%endif %}
216+
217+
<tbody>
218+
{%setprevious_event=listener %}
219+
{%endif %}
220+
221+
<tr>
222+
<tdclass="font-normal">{{ profiler_dump(listener.stub) }}</td>
223+
<tdclass="no-wrap">{{'%0.2f'|format(listener.time *1000) }} ms</td>
224+
<tdclass="font-normal">{{listener.response? profiler_dump(listener.response):'(none)' }}</td>
225+
</tr>
226+
227+
{%ifloop.last %}
228+
</tbody>
229+
{%endif %}
230+
{%endfor %}
231+
</table>
232+
{%endif %}
191233
{%endif %}
192234
{%elseifcollector.enabled %}
193235
<divclass="empty">

‎src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php‎

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@
1313

1414
usePHPUnit\Framework\TestCase;
1515
useSymfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector;
16+
useSymfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener;
1617
useSymfony\Bundle\SecurityBundle\Security\FirewallConfig;
1718
useSymfony\Bundle\SecurityBundle\Security\FirewallMap;
19+
useSymfony\Component\EventDispatcher\EventDispatcher;
20+
useSymfony\Component\HttpKernel\Event\GetResponseEvent;
21+
useSymfony\Component\HttpKernel\HttpKernelInterface;
1822
useSymfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
1923
useSymfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
2024
useSymfony\Component\Security\Core\Role\Role;
2125
useSymfony\Component\Security\Core\Role\RoleHierarchy;
26+
useSymfony\Component\Security\Http\Firewall\ListenerInterface;
2227
useSymfony\Component\Security\Http\FirewallMapInterface;
28+
useSymfony\Component\Security\Http\Logout\LogoutUrlGenerator;
2329

2430
class SecurityDataCollectorTestextends TestCase
2531
{
@@ -89,7 +95,7 @@ public function testGetFirewall()
8995
->with($request)
9096
->willReturn($firewallConfig);
9197

92-
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap);
98+
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap,newTraceableFirewallListener($firewallMap,newEventDispatcher(),newLogoutUrlGenerator()));
9399
$collector->collect($request,$this->getResponse());
94100
$collector->lateCollect();
95101
$collected =$collector->getFirewall();
@@ -124,7 +130,7 @@ public function testGetFirewallReturnsNull()
124130
->disableOriginalConstructor()
125131
->getMock();
126132

127-
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap);
133+
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap,newTraceableFirewallListener($firewallMap,newEventDispatcher(),newLogoutUrlGenerator()));
128134
$collector->collect($request,$response);
129135
$this->assertNull($collector->getFirewall());
130136

@@ -134,11 +140,50 @@ public function testGetFirewallReturnsNull()
134140
->disableOriginalConstructor()
135141
->getMock();
136142

137-
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap);
143+
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap,newTraceableFirewallListener($firewallMap,newEventDispatcher(),newLogoutUrlGenerator()));
138144
$collector->collect($request,$response);
139145
$this->assertNull($collector->getFirewall());
140146
}
141147

148+
/**
149+
* @group time-sensitive
150+
*/
151+
publicfunctiontestGetListeners()
152+
{
153+
$request =$this->getRequest();
154+
$event =newGetResponseEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(),$request, HttpKernelInterface::MASTER_REQUEST);
155+
$event->setResponse($response =$this->getResponse());
156+
$listener =$this->getMockBuilder(ListenerInterface::class)->getMock();
157+
$listener
158+
->expects($this->once())
159+
->method('handle')
160+
->with($event);
161+
$firewallMap =$this
162+
->getMockBuilder(FirewallMap::class)
163+
->disableOriginalConstructor()
164+
->getMock();
165+
$firewallMap
166+
->expects($this->any())
167+
->method('getFirewallConfig')
168+
->with($request)
169+
->willReturn(null);
170+
$firewallMap
171+
->expects($this->once())
172+
->method('getListeners')
173+
->with($request)
174+
->willReturn(array(array($listener),null));
175+
176+
$firewall =newTraceableFirewallListener($firewallMap,newEventDispatcher(),newLogoutUrlGenerator());
177+
$firewall->onKernelRequest($event);
178+
179+
$collector =newSecurityDataCollector(null,null,null,null,$firewallMap,$firewall);
180+
$collector->collect($request,$response);
181+
182+
$this->assertNotEmpty($collected =$collector->getListeners()[0]);
183+
$collector->lateCollect();
184+
$this->addToAssertionCount(1);
185+
}
186+
142187
publicfunctionprovideRoles()
143188
{
144189
returnarray(

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp