[security] Fetching current stored context when not explicitly specified
This commit is contained in:
parent
da9d88d8c5
commit
f6046ba4f3
@ -12,8 +12,9 @@
|
|||||||
<services>
|
<services>
|
||||||
<service id="templating.helper.logout_url" class="%templating.helper.logout_url.class%">
|
<service id="templating.helper.logout_url" class="%templating.helper.logout_url.class%">
|
||||||
<tag name="templating.helper" alias="logout_url" />
|
<tag name="templating.helper" alias="logout_url" />
|
||||||
<argument type="service" id="service_container" />
|
<argument type="service" id="request_stack" />
|
||||||
<argument type="service" id="router" />
|
<argument type="service" id="router" />
|
||||||
|
<argument type="service" id="security.token_storage" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="templating.helper.security" class="%templating.helper.security.class%">
|
<service id="templating.helper.security" class="%templating.helper.security.class%">
|
||||||
|
@ -14,7 +14,9 @@ namespace Symfony\Bundle\SecurityBundle\Templating\Helper;
|
|||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
|
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter;
|
||||||
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||||
use Symfony\Component\Templating\Helper\Helper;
|
use Symfony\Component\Templating\Helper\Helper;
|
||||||
|
|
||||||
@ -25,20 +27,33 @@ use Symfony\Component\Templating\Helper\Helper;
|
|||||||
*/
|
*/
|
||||||
class LogoutUrlHelper extends Helper
|
class LogoutUrlHelper extends Helper
|
||||||
{
|
{
|
||||||
private $container;
|
private $requestStack;
|
||||||
private $listeners = array();
|
private $listeners = array();
|
||||||
private $router;
|
private $router;
|
||||||
|
private $tokenStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
*
|
*
|
||||||
* @param ContainerInterface $container A ContainerInterface instance
|
* @param ContainerInterface|RequestStack $requestStack A ContainerInterface instance or RequestStack
|
||||||
* @param UrlGeneratorInterface $router A Router instance
|
* @param UrlGeneratorInterface $router The router service
|
||||||
|
* @param TokenStorageInterface|null $tokenStorage The token storage service
|
||||||
|
*
|
||||||
|
* @deprecated Passing a ContainerInterface as a first argument is deprecated since 2.7 and will be removed in 3.0.
|
||||||
*/
|
*/
|
||||||
public function __construct(ContainerInterface $container, UrlGeneratorInterface $router)
|
public function __construct($requestStack, UrlGeneratorInterface $router, TokenStorageInterface $tokenStorage = null)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
if ($requestStack instanceof ContainerInterface) {
|
||||||
|
$this->requestStack = $requestStack->get('request_stack');
|
||||||
|
trigger_error('The '.__CLASS__.' constructor will require a RequestStack instead of a ContainerInterface instance in 3.0.', E_USER_DEPRECATED);
|
||||||
|
} elseif ($requestStack instanceof RequestStack) {
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
} else {
|
||||||
|
throw new \InvalidArgumentException(sprintf('%s takes either a RequestStack or a ContainerInterface object as its first argument.', __METHOD__));
|
||||||
|
}
|
||||||
|
|
||||||
$this->router = $router;
|
$this->router = $router;
|
||||||
|
$this->tokenStorage = $tokenStorage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,7 +79,7 @@ class LogoutUrlHelper extends Helper
|
|||||||
/**
|
/**
|
||||||
* Generates the absolute logout path for the firewall.
|
* Generates the absolute logout path for the firewall.
|
||||||
*
|
*
|
||||||
* @param string $key The firewall key
|
* @param string|null $key The firewall key or null to use the current firewall key
|
||||||
*
|
*
|
||||||
* @return string The logout path
|
* @return string The logout path
|
||||||
*/
|
*/
|
||||||
@ -76,7 +91,7 @@ class LogoutUrlHelper extends Helper
|
|||||||
/**
|
/**
|
||||||
* Generates the absolute logout URL for the firewall.
|
* Generates the absolute logout URL for the firewall.
|
||||||
*
|
*
|
||||||
* @param string $key The firewall key
|
* @param string|null $key The firewall key or null to use the current firewall key
|
||||||
*
|
*
|
||||||
* @return string The logout URL
|
* @return string The logout URL
|
||||||
*/
|
*/
|
||||||
@ -88,15 +103,27 @@ class LogoutUrlHelper extends Helper
|
|||||||
/**
|
/**
|
||||||
* Generates the logout URL for the firewall.
|
* Generates the logout URL for the firewall.
|
||||||
*
|
*
|
||||||
* @param string $key The firewall key
|
* @param string|null $key The firewall key or null to use the current firewall key
|
||||||
* @param bool|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
|
* @param bool|string $referenceType The type of reference (one of the constants in UrlGeneratorInterface)
|
||||||
*
|
*
|
||||||
* @return string The logout URL
|
* @return string The logout URL
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException if no LogoutListener is registered for the key
|
* @throws \InvalidArgumentException if no LogoutListener is registered for the key or the key could not be found automatically.
|
||||||
*/
|
*/
|
||||||
private function generateLogoutUrl($key, $referenceType)
|
private function generateLogoutUrl($key, $referenceType)
|
||||||
{
|
{
|
||||||
|
// Fetch the current provider key from token, if possible
|
||||||
|
if (null === $key && null !== $this->tokenStorage) {
|
||||||
|
$token = $this->tokenStorage->getToken();
|
||||||
|
if (null !== $token && method_exists($token, 'getProviderKey')) {
|
||||||
|
$key = $token->getProviderKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $key) {
|
||||||
|
throw new \InvalidArgumentException('Unable to find the current firewall LogoutListener, please provide the provider key manually.');
|
||||||
|
}
|
||||||
|
|
||||||
if (!array_key_exists($key, $this->listeners)) {
|
if (!array_key_exists($key, $this->listeners)) {
|
||||||
throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".', $key));
|
throw new \InvalidArgumentException(sprintf('No LogoutListener found for firewall key "%s".', $key));
|
||||||
}
|
}
|
||||||
@ -106,7 +133,7 @@ class LogoutUrlHelper extends Helper
|
|||||||
$parameters = null !== $csrfTokenManager ? array($csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)) : array();
|
$parameters = null !== $csrfTokenManager ? array($csrfParameter => (string) $csrfTokenManager->getToken($csrfTokenId)) : array();
|
||||||
|
|
||||||
if ('/' === $logoutPath[0]) {
|
if ('/' === $logoutPath[0]) {
|
||||||
$request = $this->container->get('request_stack')->getCurrentRequest();
|
$request = $this->requestStack->getCurrentRequest();
|
||||||
|
|
||||||
$url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBasePath().$logoutPath;
|
$url = UrlGeneratorInterface::ABSOLUTE_URL === $referenceType ? $request->getUriForPath($logoutPath) : $request->getBasePath().$logoutPath;
|
||||||
|
|
||||||
|
@ -3,4 +3,14 @@
|
|||||||
{% block body %}
|
{% block body %}
|
||||||
Hello {{ app.user.username }}!<br /><br />
|
Hello {{ app.user.username }}!<br /><br />
|
||||||
You're browsing to path "{{ app.request.pathInfo }}".
|
You're browsing to path "{{ app.request.pathInfo }}".
|
||||||
|
|
||||||
|
<a href="{{ logout_path('default') }}">Log out</a>.
|
||||||
|
<a href="{{ logout_url('default') }}">Log out</a>.
|
||||||
|
|
||||||
|
<a href="{{ logout_path('second_area') }}">Log out</a>.
|
||||||
|
<a href="{{ logout_url('second_area') }}">Log out</a>.
|
||||||
|
|
||||||
|
<a href="{{ logout_path() }}">Log out</a>.
|
||||||
|
<a href="{{ logout_url() }}">Log out</a>.
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -36,6 +36,40 @@ class FormLoginTest extends WebTestCase
|
|||||||
$this->assertContains('You\'re browsing to path "/profile".', $text);
|
$this->assertContains('You\'re browsing to path "/profile".', $text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider getConfigs
|
||||||
|
*/
|
||||||
|
public function testFormLogout($config)
|
||||||
|
{
|
||||||
|
$client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
|
||||||
|
$client->insulate();
|
||||||
|
|
||||||
|
$form = $client->request('GET', '/login')->selectButton('login')->form();
|
||||||
|
$form['_username'] = 'johannes';
|
||||||
|
$form['_password'] = 'test';
|
||||||
|
$client->submit($form);
|
||||||
|
|
||||||
|
$this->assertRedirect($client->getResponse(), '/profile');
|
||||||
|
|
||||||
|
$crawler = $client->followRedirect();
|
||||||
|
$text = $crawler->text();
|
||||||
|
|
||||||
|
$this->assertContains('Hello johannes!', $text);
|
||||||
|
$this->assertContains('You\'re browsing to path "/profile".', $text);
|
||||||
|
|
||||||
|
$logoutLinks = $crawler->selectLink('Log out')->links();
|
||||||
|
$this->assertCount(6, $logoutLinks);
|
||||||
|
$this->assertSame($logoutLinks[0]->getUri(), $logoutLinks[1]->getUri());
|
||||||
|
$this->assertSame($logoutLinks[2]->getUri(), $logoutLinks[3]->getUri());
|
||||||
|
$this->assertSame($logoutLinks[4]->getUri(), $logoutLinks[5]->getUri());
|
||||||
|
|
||||||
|
$this->assertNotSame($logoutLinks[0]->getUri(), $logoutLinks[2]->getUri());
|
||||||
|
$this->assertNotSame($logoutLinks[1]->getUri(), $logoutLinks[3]->getUri());
|
||||||
|
|
||||||
|
$this->assertSame($logoutLinks[0]->getUri(), $logoutLinks[4]->getUri());
|
||||||
|
$this->assertSame($logoutLinks[1]->getUri(), $logoutLinks[5]->getUri());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider getConfigs
|
* @dataProvider getConfigs
|
||||||
*/
|
*/
|
||||||
|
@ -23,8 +23,17 @@ security:
|
|||||||
form_login:
|
form_login:
|
||||||
check_path: /login_check
|
check_path: /login_check
|
||||||
default_target_path: /profile
|
default_target_path: /profile
|
||||||
|
logout: ~
|
||||||
anonymous: ~
|
anonymous: ~
|
||||||
|
|
||||||
|
# This firewall is here just to check its the logout functionality
|
||||||
|
second_area:
|
||||||
|
http_basic: ~
|
||||||
|
anonymous: ~
|
||||||
|
logout:
|
||||||
|
target: /second/target
|
||||||
|
path: /second/logout
|
||||||
|
|
||||||
access_control:
|
access_control:
|
||||||
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||||
- { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
- { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
|
||||||
|
@ -41,11 +41,11 @@ class LogoutUrlExtension extends \Twig_Extension
|
|||||||
/**
|
/**
|
||||||
* Generates the relative logout URL for the firewall.
|
* Generates the relative logout URL for the firewall.
|
||||||
*
|
*
|
||||||
* @param string $key The firewall key
|
* @param string|null $key The firewall key or null to use the current firewall key
|
||||||
*
|
*
|
||||||
* @return string The relative logout URL
|
* @return string The relative logout URL
|
||||||
*/
|
*/
|
||||||
public function getLogoutPath($key)
|
public function getLogoutPath($key = null)
|
||||||
{
|
{
|
||||||
return $this->helper->getLogoutPath($key);
|
return $this->helper->getLogoutPath($key);
|
||||||
}
|
}
|
||||||
@ -53,11 +53,11 @@ class LogoutUrlExtension extends \Twig_Extension
|
|||||||
/**
|
/**
|
||||||
* Generates the absolute logout URL for the firewall.
|
* Generates the absolute logout URL for the firewall.
|
||||||
*
|
*
|
||||||
* @param string $key The firewall key
|
* @param string|null $key The firewall key or null to use the current firewall key
|
||||||
*
|
*
|
||||||
* @return string The absolute logout URL
|
* @return string The absolute logout URL
|
||||||
*/
|
*/
|
||||||
public function getLogoutUrl($key)
|
public function getLogoutUrl($key = null)
|
||||||
{
|
{
|
||||||
return $this->helper->getLogoutUrl($key);
|
return $this->helper->getLogoutUrl($key);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user