Skip to content

Commit

Permalink
Adding new TargetPathTrait to get/set the authentication "target_path"
Browse files Browse the repository at this point in the history
  • Loading branch information
weaverryan authored and fabpot committed Mar 2, 2016
1 parent 0813705 commit 18dfe37
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 4 deletions.
Expand Up @@ -17,6 +17,7 @@
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

/**
* A base class to make form login authentication easier!
Expand All @@ -25,6 +26,8 @@
*/
abstract class AbstractFormLoginAuthenticator extends AbstractGuardAuthenticator
{
use TargetPathTrait;

/**
* Return the URL to the login page.
*
Expand Down Expand Up @@ -71,7 +74,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token,
{
// if the user hit a secure page and start() was called, this was
// the URL they were on, and probably where you want to redirect to
$targetPath = $request->getSession()->get('_security.'.$providerKey.'.target_path');
$targetPath = $this->getTargetPath($request->getSession(), $providerKey);

if (!$targetPath) {
$targetPath = $this->getDefaultSuccessRedirectUrl();
Expand Down
Expand Up @@ -13,6 +13,7 @@

use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\Security\Http\ParameterBagUtils;

Expand All @@ -25,6 +26,8 @@
*/
class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandlerInterface
{
use TargetPathTrait;

protected $httpUtils;
protected $options;
protected $providerKey;
Expand Down Expand Up @@ -113,8 +116,8 @@ protected function determineTargetUrl(Request $request)
return $targetUrl;
}

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

return $targetUrl;
}
Expand Down
Expand Up @@ -22,6 +22,7 @@
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\Exception\InsufficientAuthenticationException;
use Symfony\Component\Security\Core\Exception\LogoutException;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
use Symfony\Component\Security\Http\HttpUtils;
use Symfony\Component\HttpFoundation\Request;
use Psr\Log\LoggerInterface;
Expand All @@ -39,6 +40,8 @@
*/
class ExceptionListener
{
use TargetPathTrait;

private $tokenStorage;
private $providerKey;
private $accessDeniedHandler;
Expand Down Expand Up @@ -210,7 +213,7 @@ protected function setTargetPath(Request $request)
{
// session isn't required when using HTTP basic authentication mechanism for example
if ($request->hasSession() && $request->isMethodSafe() && !$request->isXmlHttpRequest()) {
$request->getSession()->set('_security.'.$this->providerKey.'.target_path', $request->getUri());
$this->saveTargetPath($request->getSession(), $this->providerKey, $request->getUri());
}
}
}
@@ -0,0 +1,76 @@
<?php

namespace Symfony\Component\Security\Http\Tests\Util;

use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class TargetPathTraitTest extends \PHPUnit_Framework_TestCase
{
public function testSetTargetPath()
{
$obj = new TestClassWithTargetPathTrait();

$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
->getMock();

$session->expects($this->once())
->method('set')
->with('_security.firewall_name.target_path', '/foo');

$obj->doSetTargetPath($session, 'firewall_name', '/foo');
}

public function testGetTargetPath()
{
$obj = new TestClassWithTargetPathTrait();

$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
->getMock();

$session->expects($this->once())
->method('get')
->with('_security.cool_firewall.target_path')
->willReturn('/bar');

$actualUri = $obj->doGetTargetPath($session, 'cool_firewall');
$this->assertEquals(
'/bar',
$actualUri
);
}

public function testRemoveTargetPath()
{
$obj = new TestClassWithTargetPathTrait();

$session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')
->getMock();

$session->expects($this->once())
->method('remove')
->with('_security.best_firewall.target_path');

$obj->doRemoveTargetPath($session, 'best_firewall');
}
}

class TestClassWithTargetPathTrait
{
use TargetPathTrait;

public function doSetTargetPath(SessionInterface $session, $providerKey, $uri)
{
$this->saveTargetPath($session, $providerKey, $uri);
}

public function doGetTargetPath(SessionInterface $session, $providerKey)
{
return $this->getTargetPath($session, $providerKey);
}

public function doRemoveTargetPath(SessionInterface $session, $providerKey)
{
$this->removeTargetPath($session, $providerKey);
}
}
58 changes: 58 additions & 0 deletions src/Symfony/Component/Security/Http/Util/TargetPathTrait.php
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Security\Http\Util;

use Symfony\Component\HttpFoundation\Session\SessionInterface;

/**
* Trait to get (and set) the URL the user last visited before being forced to authenticate.
*/
trait TargetPathTrait
{
/**
* Set the target path the user should be redirected to after authentication.
*
* Usually, you do not need to set this directly.
*
* @param SessionInterface $session
* @param string $providerKey The name of your firewall
* @param string $uri The URI to set as the target path
*/
private function saveTargetPath(SessionInterface $session, $providerKey, $uri)
{
$session->set('_security.'.$providerKey.'.target_path', $uri);
}

/**
* Returns the URL (if any) the user visited that forced them to login.
*
* @param SessionInterface $session
* @param string $providerKey The name of your firewall
*
* @return string
*/
private function getTargetPath(SessionInterface $session, $providerKey)
{
return $session->get('_security.'.$providerKey.'.target_path');
}

/**
* Removes the target path from the session.
*
* @param SessionInterface $session
* @param string $providerKey The name of your firewall
*/
private function removeTargetPath(SessionInterface $session, $providerKey)
{
$session->remove('_security.'.$providerKey.'.target_path');
}
}

0 comments on commit 18dfe37

Please sign in to comment.