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 388ae55

Browse filesBrowse files
committed
feature #13342 [security] Fetching current stored context when not explicitly specified (jaytaph)
This PR was squashed before being merged into the 2.7 branch (closes #13342). Discussion ---------- [security] Fetching current stored context when not explicitly specified | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #12160 | License | MIT | Doc PR | N/A This patch will use the current stored context found in a token (provided, there is one), if none has been specified. According to a quick scan of the code, this will be the only place where `getProviderKey()` is used outside a specific class (the authentication providers will check token type before calling `getProviderKey()`, but maybe it's be a good idea to implement a "providerKeyTokenInterface" or something. It's a nicer solution imho than the current `method_exists()` Commits ------- f6046ba [security] Fetching current stored context when not explicitly specified
2 parents e756135 + f6046ba commit 388ae55
Copy full SHA for 388ae55

File tree

Expand file treeCollapse file tree

6 files changed

+96
-15
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

6 files changed

+96
-15
lines changed
Open diff view settings
Collapse file

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Resources/config/templating_php.xml
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
<services>
1313
<service id="templating.helper.logout_url" class="%templating.helper.logout_url.class%">
1414
<tag name="templating.helper" alias="logout_url" />
15-
<argument type="service" id="service_container" />
15+
<argument type="service" id="request_stack" />
1616
<argument type="service" id="router" />
17+
<argument type="service" id="security.token_storage" />
1718
</service>
1819

1920
<service id="templating.helper.security" class="%templating.helper.security.class%">
Collapse file

‎src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php
+37-10Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@
1414
use Symfony\Component\DependencyInjection\ContainerInterface;
1515
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
1616
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
17+
use Symfony\Component\HttpFoundation\RequestStack;
1718
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
19+
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
1820
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
1921
use Symfony\Component\Templating\Helper\Helper;
2022

@@ -25,20 +27,33 @@
2527
*/
2628
class LogoutUrlHelper extends Helper
2729
{
28-
private $container;
30+
private $requestStack;
2931
private $listeners = array();
3032
private $router;
33+
private $tokenStorage;
3134

3235
/**
3336
* Constructor.
3437
*
35-
* @param ContainerInterface $container A ContainerInterface instance
36-
* @param UrlGeneratorInterface $router A Router instance
38+
* @param ContainerInterface|RequestStack $requestStack A ContainerInterface instance or RequestStack
39+
* @param UrlGeneratorInterface $router The router service
40+
* @param TokenStorageInterface|null $tokenStorage The token storage service
41+
*
42+
* @deprecated Passing a ContainerInterface as a first argument is deprecated since 2.7 and will be removed in 3.0.
3743
*/
38-
public function __construct(ContainerInterface $container, UrlGeneratorInterface $router)
44+
public function __construct($requestStack, UrlGeneratorInterface $router, TokenStorageInterface $tokenStorage = null)
3945
{
40-
$this->container = $container;
46+
if ($requestStack instanceof ContainerInterface) {
47+
$this->requestStack = $requestStack->get('request_stack');
48+
trigger_error('The '.__CLASS__.' constructor will require a RequestStack instead of a ContainerInterface instance in 3.0.', E_USER_DEPRECATED);
49+
} elseif ($requestStack instanceof RequestStack) {
50+
$this->requestStack = $requestStack;
51+
} else {
52+
throw new \InvalidArgumentException(sprintf('%s takes either a RequestStack or a ContainerInterface object as its first argument.', __METHOD__));
53+
}
54+
4155
$this->router = $router;
56+
$this->tokenStorage = $tokenStorage;
4257
}
4358

4459
/**
@@ -64,7 +79,7 @@ public function registerListener($key, $logoutPath, $csrfTokenId, $csrfParameter
6479
/**
6580
* Generates the absolute logout path for the firewall.
6681
*
67-
* @param string $key The firewall key
82+
* @param string|null $key The firewall key or null to use the current firewall key
6883
*
6984
* @return string The logout path
7085
*/
@@ -76,7 +91,7 @@ public function getLogoutPath($key)
7691
/**
7792
* Generates the absolute logout URL for the firewall.
7893
*
79-
* @param string $key The firewall key
94+
* @param string|null $key The firewall key or null to use the current firewall key
8095
*
8196
* @return string The logout URL
8297
*/
@@ -88,15 +103,27 @@ public function getLogoutUrl($key)
88103
/**
89104
* Generates the logout URL for the firewall.
90105
*
91-
* @param string $key The firewall key
106+
* @param string|null $key The firewall key or null to use the current firewall key
92107
* @param bool|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
93108
*
94109
* @return string The logout URL
95110
*
96-
* @throws \InvalidArgumentException if no LogoutListener is registered for the key
111+
* @throws \InvalidArgumentException if no LogoutListener is registered for the key or the key could not be found automatically.
97112
*/
98113
private function generateLogoutUrl($key, $referenceType)
99114
{
115+
// Fetch the current provider key from token, if possible
116+
if (null === $key && null !== $this->tokenStorage) {
117+
$token = $this->tokenStorage->getToken();
118+
if (null !== $token && method_exists($token, 'getProviderKey')) {
119+
$key = $token->getProviderKey();
120+
}
121+
}
122+
123+
if (null === $key) {
124+
throw new \InvalidArgumentException('Unable to find the current firewall LogoutListener, please provide the provider key manually.');
125+
}
126+
100127
if (!array_key_exists($key, $this->listeners)) {
101128
throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".', $key));
102129
}
@@ -106,7 +133,7 @@ private function generateLogoutUrl($key, $referenceType)
106133
$parameters = null !== $csrfTokenManager ? array($csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)) : array();
107134

108135
if ('/' === $logoutPath[0]) {
109-
$request = $this->container->get('request_stack')->getCurrentRequest();
136+
$request = $this->requestStack->getCurrentRequest();
110137

111138
$url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBasePath().$logoutPath;
112139

Collapse file

‎src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig‎

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Login/after_login.html.twig
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,14 @@
33
{% block body %}
44
Hello {{ app.user.username }}!<br /><br />
55
You're browsing to path "{{ app.request.pathInfo }}".
6+
7+
<a href="{{ logout_path('default') }}">Log out</a>.
8+
<a href="{{ logout_url('default') }}">Log out</a>.
9+
10+
<a href="{{ logout_path('second_area') }}">Log out</a>.
11+
<a href="{{ logout_url('second_area') }}">Log out</a>.
12+
13+
<a href="{{ logout_path() }}">Log out</a>.
14+
<a href="{{ logout_url() }}">Log out</a>.
15+
616
{% endblock %}
Collapse file

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
+34Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,40 @@ public function testFormLogin($config)
3636
$this->assertContains('You\'re browsing to path "/profile".', $text);
3737
}
3838

39+
/**
40+
* @dataProvider getConfigs
41+
*/
42+
public function testFormLogout($config)
43+
{
44+
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
45+
$client->insulate();
46+
47+
$form = $client->request('GET', '/login')->selectButton('login')->form();
48+
$form['_username'] = 'johannes';
49+
$form['_password'] = 'test';
50+
$client->submit($form);
51+
52+
$this->assertRedirect($client->getResponse(), '/profile');
53+
54+
$crawler = $client->followRedirect();
55+
$text = $crawler->text();
56+
57+
$this->assertContains('Hello johannes!', $text);
58+
$this->assertContains('You\'re browsing to path "/profile".', $text);
59+
60+
$logoutLinks = $crawler->selectLink('Log out')->links();
61+
$this->assertCount(6, $logoutLinks);
62+
$this->assertSame($logoutLinks[0]->getUri(), $logoutLinks[1]->getUri());
63+
$this->assertSame($logoutLinks[2]->getUri(), $logoutLinks[3]->getUri());
64+
$this->assertSame($logoutLinks[4]->getUri(), $logoutLinks[5]->getUri());
65+
66+
$this->assertNotSame($logoutLinks[0]->getUri(), $logoutLinks[2]->getUri());
67+
$this->assertNotSame($logoutLinks[1]->getUri(), $logoutLinks[3]->getUri());
68+
69+
$this->assertSame($logoutLinks[0]->getUri(), $logoutLinks[4]->getUri());
70+
$this->assertSame($logoutLinks[1]->getUri(), $logoutLinks[5]->getUri());
71+
}
72+
3973
/**
4074
* @dataProvider getConfigs
4175
*/
Collapse file

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

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml
+9Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,17 @@ security:
2323
form_login:
2424
check_path: /login_check
2525
default_target_path: /profile
26+
logout: ~
2627
anonymous: ~
2728

29+
# This firewall is here just to check its the logout functionality
30+
second_area:
31+
http_basic: ~
32+
anonymous: ~
33+
logout:
34+
target: /second/target
35+
path: /second/logout
36+
2837
access_control:
2938
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
3039
- { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
Collapse file

‎src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php‎

Copy file name to clipboardExpand all lines: src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,23 @@ public function getFunctions()
4141
/**
4242
* Generates the relative logout URL for the firewall.
4343
*
44-
* @param string $key The firewall key
44+
* @param string|null $key The firewall key or null to use the current firewall key
4545
*
4646
* @return string The relative logout URL
4747
*/
48-
public function getLogoutPath($key)
48+
public function getLogoutPath($key = null)
4949
{
5050
return $this->helper->getLogoutPath($key);
5151
}
5252

5353
/**
5454
* Generates the absolute logout URL for the firewall.
5555
*
56-
* @param string $key The firewall key
56+
* @param string|null $key The firewall key or null to use the current firewall key
5757
*
5858
* @return string The absolute logout URL
5959
*/
60-
public function getLogoutUrl($key)
60+
public function getLogoutUrl($key = null)
6161
{
6262
return $this->helper->getLogoutUrl($key);
6363
}

0 commit comments

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