8000 Integrate current firewall in profiler · symfony/symfony@be2a55b · GitHub
[go: up one dir, main page]

Skip to content

Commit be2a55b

Browse files
committed
Integrate current firewall in profiler
Add firewall name to the toolbar Display bool values as metrics, Dont display request_matcher anymore Use allowsAnonymous()/isSecurityEnabled() in template, update labels accordingly Add SecurityDataCollectorTest::testCollectFirewall() Move collector.enabled check higher to cover token+firewall sections Allow Anonymous => Allows anonymous Tests null cases for SecurityDataCollector::getFirewall() Fix phpdoc block Normalize as array in security data collector
1 parent 904e90b commit be2a55b

File tree

4 files changed

+230
-46
lines changed

4 files changed

+230
-46
lines changed

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
2222
use Symfony\Component\Security\Core\Authorization\DebugAccessDecisionManager;
2323
use Symfony\Component\VarDumper\Cloner\Data;
24+
use Symfony\Component\Security\Http\FirewallMapInterface;
25+
use Symfony\Bundle\SecurityBundle\Security\FirewallMAp;
2426

2527
/**
2628
* SecurityDataCollector.
@@ -33,6 +35,7 @@ class SecurityDataCollector extends DataCollector
3335
private $roleHierarchy;
3436
private $logoutUrlGenerator;
3537
private $accessDecisionManager;
38+
private $firewallMap;
3639

3740
/**
3841
* Constructor.
@@ -41,13 +44,15 @@ class SecurityDataCollector extends DataCollector
4144
* @param RoleHierarchyInterface|null $roleHierarchy
4245
* @param LogoutUrlGenerator|null $logoutUrlGenerator
4346
* @param AccessDecisionManagerInterface|null $accessDecisionManager
47+
* @param FirewallMapInterface|null $firewallMap
4448
*/
45-
public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null)
49+
public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $ro 9E88 leHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null, FirewallMapInterface $firewallMap = null)
4650
{
4751
$this->tokenStorage = $tokenStorage;
4852
$this->roleHierarchy = $roleHierarchy;
4953
$this->logoutUrlGenerator = $logoutUrlGenerator;
5054
$this->accessDecisionManager = $accessDecisionManager;
55+
$this->firewallMap = $firewallMap;
5156
}
5257

5358
/**
@@ -132,6 +137,28 @@ public function collect(Request $request, Response $response, \Exception $except
132137
$this->data['voter_strategy'] = 'unknown';
133138
$this->data['voters'] = array();
134139
}
140+
141+
// collect firewall context information
142+
$this->data['firewall'] = null;
143+
if ($this->firewallMap instanceof FirewallMap) {
144+
$firewallConfig = $this->firewallMap->getFirewallConfig($request);
145+
if (null !== $firewallConfig) {
146+
$this->data['firewall'] = array(
147+
'name' => $firewallConfig->getName(),
148+
'allows_anonymous' => $firewallConfig< F438 /span>->allowsAnonymous(),
149+
'request_matcher' => $firewallConfig->getRequestMatcher(),
150+
'security_enabled' => $firewallConfig->isSecurityEnabled(),
151+
'stateless' => $firewallConfig->isStateless(),
152+
'provider' => $firewallConfig->getProvider(),
153+
'context' => $firewallConfig->getContext(),
154+
'entry_point' => $firewallConfig->getEntryPoint(),
155+
'access_denied_handler' => $firewallConfig->getAccessDeniedHandler(),
156+
'access_denied_url' => $firewallConfig->getAccessDeniedUrl(),
157+
'user_checker' => $firewallConfig->getUserChecker(),
158+
'listeners' => $this->cloneVar($firewallConfig->getListeners()),
159+
);
160+
}
161+
}
135162
}
136163

137164
/**
@@ -255,6 +282,16 @@ public function getAccessDecisionLog()
255282
return $this->data['access_decision_log'];
256283
}
257284

285+
/**
286+
* Returns the configuration of the current firewall context.
287+
*
288+
* @return array
289+
*/
290+
public function getFirewall()
291+
{
292+
return $this->data['firewall'];
293+
}
294+
258295
/**
259296
* {@inheritdoc}
260297
*/

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<argument type="service" id="security.role_hierarchy" />
1212
<argument type="service" id="security.logout_url_generator" />
1313
<argument type="service" id="security.access.decision_manager" />
14+
<argument type="service" id="security.firewall.map" />
1415
</service>
1516
</services>
1617
</container>

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

Lines changed: 121 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@
3333
<span>{{ collector.tokenClass|abbr_class }}</span>
3434
</div>
3535
{% endif %}
36+
{% if collector.firewall %}
37+
<div class="sf-toolbar-info-piece">
38+
<b>Firewall name</b>
39+
<span>{{ collector.firewall.name }}</span>
40+
</div>
41+
{% endif %}
3642
{% if collector.logoutUrl %}
3743
<div class="sf-toolbar-info-piece">
3844
<b>Actions</b>
@@ -63,57 +69,127 @@
6369
{% block panel %}
6470
<h2>Security Token</h2>
6571

66-
{% if collector.token %}
67-
<div class="metrics">
68-
<div class="metric">
69-
<span class="value">{{ collector.user == 'anon.' ? 'Anonymous' : collector.user }}</span>
70-
<span class="label">Username</span>
72+
{% if collector.enabled %}
73+
{% if collector.token %}
74+
<div class="metrics">
75+
<div class="metric">
76+
<span class="value">{{ collector.user == 'anon.' ? 'Anonymous' : collector.user }}</span>
77+
<span class="label">Username</span>
78+
</div>
79+
80+
<div class="metric">
81+
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
82+
<span class="label">Authenticated</span>
83+
</div>
7184
</div>
7285

73-
<div class="metric">
74-
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}</span>
75-
<span class="label">Authenticated</span>
86+
<table>
87+
<thead>
88+
<tr>
89+
<th scope="col" class="key">Property</th>
90+
<th scope="col">Value</th>
91+
</tr>
92+
</thead>
93+
<tbody>
94+
<tr>
95+
<th>Roles</th>
96+
<td>
97+
{{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}
98+
99+
{% if not collector.authenticated and collector.roles is empty %}
100+
<p class="help">User is not authenticated probably because they have no roles.</p>
101+
{% endif %}
102+
</td>
103+
</tr>
104+
105+
{% if collector.supportsRoleHierarchy %}
106+
<tr>
107+
<th>Inherited Roles</th>
108+
<td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
109+
</tr>
110+
{% endif %}
111+
112+
{% if collector.token %}
113+
<tr>
114+
<th>Token</th>
115+
<td>{{ profiler_dump(collector.token) }}</td>
116+
</tr>
117+
{% endif %}
118+
</tbody>
119+
</table>
120+
{% elseif collector.enabled %}
121+
<div class="empty">
122+
<p>There is no security token.</p>
76123
</div>
77-
</div>
124+
{% endif %}
78125

79-
<table>
80-
<thead>
81-
<tr>
82-
<th scope="col" class="key">Property</th>
83-
<th scope="col">Value</th>
84-
</tr>
85-
</thead>
86-
<tbody>
87-
<tr>
88-
<th>Roles</th>
89-
<td>
90-
{{ collector.roles is empty ? 'none' : profiler_dump(collector.roles, maxDepth=1) }}
91-
92-
{% if not collector.authenticated and collector.roles 10000 is empty %}
93-
<p class="help">User is not authenticated probably because they have no roles.</p>
94-
{% endif %}
95-
</td>
96-
</tr>
97126

98-
{% if collector.supportsRoleHierarchy %}
99-
<tr>
100-
<th>Inherited Roles</th>
101-
<td>{{ collector.inheritedRoles is empty ? 'none' : profiler_dump(collector.inheritedRoles, maxDepth=1) }}</td>
102-
</tr>
103-
{% endif %}
127+
<h2>Security Firewall</h2>
104128

105-
{% if collector.token %}
106-
<tr>
107-
<th>Token</th>
108-
<td>{{ profiler_dump(collector.token) }}</td>
109-
</tr>
110-
{% endif %}
111-
</tbody>
112-
</table>
113-
{% elseif collector.enabled %}
114-
<div class="empty">
115-
<p>There is no security token.</p>
116-
</div>
129+
{% if collector.firewall %}
130+
<div class="metrics">
131+
<div class="metric">
132+
<span class="value">{{ collector.firewall.name }}</span>
133+
<span class="label">Name</span>
134+
</div>
135+
<div class="metric">
136+
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.security_enabled ? 'yes' : 'no') ~ '.svg') }}</span>
137+
<span class="label">Security enabled</span>
138+
</div>
139+
<div class="metric">
140+
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.stateless ? 'yes' : 'no') ~ '.svg') }}</span>
141+
<span class="label">Stateless</span>
142+
</div>
143+
<div class="metric">
144+
<span class="value">{{ include('@WebProfiler/Icon/' ~ (collector.firewall.allows_anonymous ? 'yes' : 'no') ~ '.svg') }}</span>
145+
<span class="label">Allows anonymous</span>
146+
</div>
147+
</div>
148+
{% if collector.firewall.security_enabled %}
149+
<table>
150+
<thead>
151+
<tr>
152+
<th scope="col" class="key">Key</th>
153+
<th scope="col">Value</th>
154+
</tr>
155+
</thead>
156+
<tbody>
157+
<tr>
158+
<th>provider</th>
159+
<td>{{ collector.firewall.provider }}</td>
160+
</tr>
161+
<tr>
162+
<th>context</th>
163+
<td>{{ collector.firewall.context }}</td>
164+
</tr>
165+
<tr>
166+
<th>entry_point</th>
167+
<td>{{ collector.firewall.entry_point }}</td>
168+
</tr>
169+
<tr>
170+
<th>user_checker</th>
171+
<td>{{ collector.firewall.user_checker }}</td>
172+
</tr>
173+
<tr>
174+
<th>access_denied_handler</th>
175+
<td>{{ collector.firewall.access_denied_handler }}</td>
176+
</tr>
177+
<tr>
178+
<th>access_denied_url</th>
179+
<td>{{ collector.firewall.access_denied_url }}</td>
180+
</tr>
181+
<tr>
182+
<th>listeners</th>
183+
<td>{{ collector.firewall.listeners is empty ? 'none' : profiler_dump(collector.firewall.listeners, maxDepth=1) }}</td>
184+
</tr>
185+
</tbody>
186+
</table>
187+
{% endif %}
188+
{% elseif collector.enabled %}
189+
<div class="empty">
190+
<p>There is no firewall.</p>
191+
</div>
192+
{% endif %}
117193
{% else %}
118194
<div class="empty">
119195
<p>The security component is disabled.</p>

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

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@
1212
namespace Symfony\Bundle\SecurityBundle\Tests\DataCollector;
1313

1414
use Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector;
15+
use Symfony\Bundle\SecurityBundle\Security\FirewallConfig;
16+
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
17+
use Symfony\Bundle\SecurityBundle\Security\FirewallMap;
1518
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
1619
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
1720
use Symfony\Component\Security\Core\Role\Role;
1821
u 10000 se Symfony\Component\Security\Core\Role\RoleHierarchy;
22+
use Symfony\Component\Security\Http\FirewallMapInterface;
1923

2024
class SecurityDataCollectorTest extends \PHPUnit_Framework_TestCase
2125
{
@@ -32,6 +36,7 @@ public function testCollectWhenSecurityIsDisabled()
3236
$this->assertCount(0, $collector->getRoles());
3337
$this->assertCount(0, $collector->getInheritedRoles());
3438
$this->assertEmpty($collector->getUser());
39+
$this->assertNull($collector->getFirewall());
3540
}
3641

3742
public function testCollectWhenAuthenticationTokenIsNull()
@@ -47,6 +52,7 @@ public function testCollectWhenAuthenticationTokenIsNull()
4752
$this->assertCount(0, $collector->getRoles());
4853
$this->assertCount(0, $collector->getInheritedRoles());
4954
$this->assertEmpty($collector->getUser());
55+
$this->assertNull($collector->getFirewall());
5056
}
5157

5258
/** @dataProvider provideRoles */
@@ -71,6 +77,70 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm
7177
$this->assertSame('hhamon', $collector->getUser());
7278
}
7379

80+
public function testGetFirewall()
81+
{
82+
$firewallConfig = new FirewallConfig('dummy', 'security.request_matcher.dummy');
83+
$request = $this->getRequest();
84+
85+
$firewallMap = $this
86+
->getMockBuilder(FirewallMap::class)
87+
->disableOriginalConstructor()
88+
->getMock();
89+
$firewallMap
90+
->expects($this->once())
91+
->method('getFirewallConfig')
92+
->with($request)
93+
->willReturn($firewallConfig);
94+
95+
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
96+
$collector->collect($request, $this->getResponse());
97+
$collected = $collector->getFirewall();
98+
99+
$this->assertSame($firewallConfig->getName(), $collected['name']);
100+
$this->assertSame($firewallConfig->allowsAnonymous(), $collected['allows_anonymous']);
101+
$this->assertSame($firewallConfig->getRequestMatcher(), $collected['request_matcher']);
102+
$this->assertSame($firewallConfig->isSecurityEnabled(), $collected['security_enabled']);
103+
$this->assertSame($firewallConfig->isStateless(), $collected['stateless']);
104+
$this->assertSame($firewallConfig->getProvider(), $collected['provider']);
105+
$this->assertSame($firewallConfig->getContext(), $collected['context']);
106+
$this->assertSame($firewallConfig->getEntryPoint(), $collected['entry_point']);
107+
$this->assertSame($firewallConfig->getAccessDeniedHandler(), $collected['access_denied_handler']);
108+
$this->assertSame($firewallConfig->getAccessDeniedUrl(), $collected['access_denied_url']);
109+
$this->assertSame($firewallConfig->getUserChecker(), $collected['user_checker']);
110+
$this->assertSame($firewallConfig->getListeners(), $collected['listeners']->getRawData()[0][0]);
111+
}
112+
113+
public function testGetFirewallReturnsNull()
114+
{
115+
$request = $this->getRequest();
116+
$response = $this->getResponse();
117+
118+
// Don't inject any firewall map
119+
$collector = new SecurityDataCollector();
120+
$collector->collect($request, $response);
121+
$this->assertNull($collector->getFirewall());
122+
123+
// Inject an instance that is not context aware
124+
$firewallMap = $this
125+
->getMockBuilder(FirewallMapInterface::class)
126+
->disableOriginalConstructor()
127+
->getMock();
128+
129+
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
130+
$collector->collect($request, $response);
131+
$this->assertNull($collector->getFirewall());
132+
133+
// Null config
134+
$firewallMap = $this
135+
->getMockBuilder(FirewallMap::class)
136+
->disableOriginalConstructor()
137+
->getMock();
138+
139+
$collector = new SecurityDataCollector(null, null, null, null, $firewallMap);
140+
$collector->collect($request, $response);
141+
$this->assertNull($collector->getFirewall());
142+
}
143+
74144
public function provideRoles()
75145
{
76146
return array(

0 commit comments

Comments
 (0)
0