Skip to content

Commit 5d6a6b3

Browse files
committed
feature symfony#17714 Adding new TargetPathTrait to get/set the authentication "target_path" (weaverryan)
This PR was squashed before being merged into the 3.1-dev branch (closes symfony#17714). Discussion ---------- Adding new TargetPathTrait to get/set the authentication "target_path" | Q | A | ------------- | --- | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | not yet... Hi guys! This is a small guy. Basically, when you're doing custom auth (i.e. a guard authenticator), it's common to need the previous URL the user tried to get to (i.e. the "target path"). It's not much work to do it now, but it's very abstract - needing to know a weird string pattern. This just wraps that weirdness up in a simple function (`getTargetPath()`). Thanks! Commits ------- 18dfe37 Adding new TargetPathTrait to get/set the authentication "target_path"
2 parents 20362f7 + 18dfe37 commit 5d6a6b3

File tree

5 files changed

+147
-4
lines changed

5 files changed

+147
-4
lines changed

src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1818
use Symfony\Component\Security\Core\Exception\AuthenticationException;
1919
use Symfony\Component\Security\Core\Security;
20+
use Symfony\Component\Security\Http\Util\TargetPathTrait;
2021

2122
/**
2223
* A base class to make form login authentication easier!
@@ -25,6 +26,8 @@
2526
*/
2627
abstract class AbstractFormLoginAuthenticator extends AbstractGuardAuthenticator
2728
{
29+
use TargetPathTrait;
30+
2831
/**
2932
* Return the URL to the login page.
3033
*
@@ -71,7 +74,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
7174
{
7275
// if the user hit a secure page and start() was called, this was
7376
// the URL they were on, and probably where you want to redirect to
74-
$targetPath = $request->getSession()->get('_security.'.$providerKey.'.target_path');
77+
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);
7578

7679
if (!$targetPath) {
7780
$targetPath = $this->getDefaultSuccessRedirectUrl();

src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
1515
use Symfony\Component\HttpFoundation\Request;
16+
use Symfony\Component\Security\Http\Util\TargetPathTrait;
1617
use Symfony\Component\Security\Http\HttpUtils;
1718
use Symfony\Component\Security\Http\ParameterBagUtils;
1819

@@ -25,6 +26,8 @@
2526
*/
2627
class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
2728
{
29+
use TargetPathTrait;
30+
2831
protected $httpUtils;
2932
protected $options;
3033
protected $providerKey;
@@ -113,8 +116,8 @@ protected function determineTargetUrl(Request $request)
113116
return $targetUrl;
114117
}
115118

116-
if (null !== $this->providerKey && $targetUrl = $request->getSession()->get('_security.'.$this->providerKey.'.target_path')) {
117-
$request->getSession()->remove('_security.'.$this->providerKey.'.target_path');
119+
if (null !== $this->providerKey && $targetUrl = $this->getTargetPath($request->getSession(), $this->providerKey)) {
120+
$this->removeTargetPath($request->getSession(), $this->providerKey);
118121

119122
return $targetUrl;
120123
}

src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
2323
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
2424
use Symfony\Component\Security\Core\Exception\LogoutException;
25+
use Symfony\Component\Security\Http\Util\TargetPathTrait;
2526
use Symfony\Component\Security\Http\HttpUtils;
2627
use Symfony\Component\HttpFoundation\Request;
2728
use Psr\Log\LoggerInterface;
@@ -39,6 +40,8 @@
3940
*/
4041
class ExceptionListener
4142
{
43+
use TargetPathTrait;
44+
4245
private $tokenStorage;
4346
private $providerKey;
4447
private $accessDeniedHandler;
@@ -210,7 +213,7 @@ protected function setTargetPath(Request $request)
210213
{
211214
// session isn't required when using HTTP basic authentication mechanism for example
212215
if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) {
213-
$request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri());
216+
$this->saveTargetPath($request->getSession(), $this->providerKey, $request->getUri());
214217
}
215218
}
216219
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<?php
2+
3+
namespace Symfony\Component\Security\Http\Tests\Util;
4+
5+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
6+
use Symfony\Component\Security\Http\Util\TargetPathTrait;
7+
8+
class TargetPathTraitTest extends \PHPUnit_Framework_TestCase
9+
{
10+
public function testSetTargetPath()
11+
{
12+
$obj = new TestClassWithTargetPathTrait();
13+
14+
$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
15+
->getMock();
16+
17+
$session->expects($this->once())
18+
->method('set')
19+
->with('_security.firewall_name.target_path', '/foo');
20+
21+
$obj->doSetTargetPath($session, 'firewall_name', '/foo');
22+
}
23+
24+
public function testGetTargetPath()
25+
{
26+
$obj = new TestClassWithTargetPathTrait();
27+
28+
$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
29+
->getMock();
30+
31+
$session->expects($this->once())
32+
->method('get')
33+
->with('_security.cool_firewall.target_path')
34+
->willReturn('/bar');
35+
36+
$actualUri = $obj->doGetTargetPath($session, 'cool_firewall');
37+
$this->assertEquals(
38+
'/bar',
39+
$actualUri
40+
);
41+
}
42+
43+
public function testRemoveTargetPath()
44+
{
45+
$obj = new TestClassWithTargetPathTrait();
46+
47+
$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
48+
->getMock();
49+
50+
$session->expects($this->once())
51+
->method('remove')
52+
->with('_security.best_firewall.target_path');
53+
54+
$obj->doRemoveTargetPath($session, 'best_firewall');
55+
}
56+
}
57+
58+
class TestClassWithTargetPathTrait
59+
{
60+
use TargetPathTrait;
61+
62+
public function doSetTargetPath(SessionInterface $session, $providerKey, $uri)
63+
{
64+
$this->saveTargetPath($session, $providerKey, $uri);
65+
}
66+
67+
public function doGetTargetPath(SessionInterface $session, $providerKey)
68+
{
69+
return $this->getTargetPath($session, $providerKey);
70+
}
71+
72+
public function doRemoveTargetPath(SessionInterface $session, $providerKey)
73+
{
74+
$this->removeTargetPath($session, $providerKey);
75+
}
76+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
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+
namespace Symfony\Component\Security\Http\Util;
13+
14+
use Symfony\Component\HttpFoundation\Session\SessionInterface;
15+
16+
/**
17+
* Trait to get (and set) the URL the user last visited before being forced to authenticate.
18+
*/
19+
trait TargetPathTrait
20+
{
21+
/**
22+
* Set the target path the user should be redirected to after authentication.
23+
*
24+
* Usually, you do not need to set this directly.
25+
*
26+
* @param SessionInterface $session
27+
* @param string $providerKey The name of your firewall
28+
* @param string $uri The URI to set as the target path
29+
*/
30+
private function saveTargetPath(SessionInterface $session, $providerKey, $uri)
31+
{
32+
$session->set('_security.'.$providerKey.'.target_path', $uri);
33+
}
34+
35+
/**
36+
* Returns the URL (if any) the user visited that forced them to login.
37+
*
38+
* @param SessionInterface $session
39+
* @param string $providerKey The name of your firewall
40+
*
41+
* @return string
42+
*/
43+
private function getTargetPath(SessionInterface $session, $providerKey)
44+
{
45+
return $session->get('_security.'.$providerKey.'.target_path');
46+
}
47+
48+
/**
49+
* Removes the target path from the session.
50+
*
51+
* @param SessionInterface $session
52+
* @param string $providerKey The name of your firewall
53+
*/
54+
private function removeTargetPath(SessionInterface $session, $providerKey)
55+
{
56+
$session->remove('_security.'.$providerKey.'.target_path');
57+
}
58+
}

0 commit comments

Comments
 (0)