diff --git a/UPDATE.md b/UPDATE.md
index 407bc43aa1a71..459156a8cdc4d 100644
--- a/UPDATE.md
+++ b/UPDATE.md
@@ -77,6 +77,9 @@ RC4 to RC5
Session::getAttributes() -> Session::all()
Session::setAttributes() -> Session::replace()
+* {_locale} is not supported in paths in the access_control section anymore. You can
+ rewrite the paths using a regular expression such as "(?:[a-z]{2})".
+
RC3 to RC4
----------
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticationCommencingTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticationCommencingTest.php
new file mode 100644
index 0000000000000..f13ea641348ed
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/AuthenticationCommencingTest.php
@@ -0,0 +1,15 @@
+createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'config.yml'));
+ $client->insulate();
+
+ $client->request('GET', '/secure-but-not-covered-by-access-control');
+ $this->assertRedirect($client->getResponse(), '/login');
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php
new file mode 100644
index 0000000000000..7ac6bbdfc8489
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LocalizedController.php
@@ -0,0 +1,51 @@
+container->get('request')->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
+ $error = $this->container->get('request')->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
+ } else {
+ $error = $this->container->get('request')->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
+ }
+
+ return $this->container->get('templating')->renderResponse('FormLoginBundle:Localized:login.html.twig', array(
+ // last username entered by the user
+ 'last_username' => $this->container->get('request')->getSession()->get(SecurityContext::LAST_USERNAME),
+ 'error' => $error,
+ ));
+ }
+
+ public function loginCheckAction()
+ {
+ throw new \RuntimeException('loginCheckAction() should never be called.');
+ }
+
+ public function logoutAction()
+ {
+ throw new \RuntimeException('logoutAction() should never be called.');
+ }
+
+ public function secureAction()
+ {
+ throw new \RuntimeException('secureAction() should never be called.');
+ }
+
+ public function profileAction()
+ {
+ return new Response('Profile');
+ }
+
+ public function homepageAction()
+ {
+ return new Response('Homepage');
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
index 2781509dc76bc..0e48ff2f19185 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Controller/LoginController.php
@@ -11,6 +11,7 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\FormLoginBundle\Controller;
+use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\DependencyInjection\ContainerAware;
@@ -42,4 +43,9 @@ public function loginCheckAction()
{
return new Response('', 400);
}
+
+ public function secureAction()
+ {
+ throw new \Exception('Wrapper', 0, new \Exception('Another Wrapper', 0, new AccessDeniedException()));
+ }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/localized_routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/localized_routing.yml
new file mode 100644
index 0000000000000..803558f30043b
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/localized_routing.yml
@@ -0,0 +1,30 @@
+localized_login_path:
+ pattern: /{_locale}/login
+ defaults: { _controller: FormLoginBundle:Localized:login }
+ requirements: { _locale: "^[a-z]{2}$" }
+
+localized_check_path:
+ pattern: /{_locale}/login_check
+ defaults: { _controller: FormLoginBundle:Localized:loginCheck }
+ requirements: { _locale: "^[a-z]{2}$" }
+
+localized_default_target_path:
+ pattern: /{_locale}/profile
+ defaults: { _controller: FormLoginBundle:Localized:profile }
+ requirements: { _locale: "^[a-z]{2}$" }
+
+localized_logout_path:
+ pattern: /{_locale}/logout
+ defaults: { _controller: FormLoginBundle:Localized:logout }
+ requirements: { _locale: "^[a-z]{2}$" }
+
+localized_logout_target_path:
+ pattern: /{_locale}/
+ defaults: { _controller: FormLoginBundle:Localized:homepage }
+ requirements: { _locale: "^[a-z]{2}$" }
+
+localized_secure_path:
+ pattern: /{_locale}/secure/
+ defaults: { _controller: FormLoginBundle:Localized:secure }
+ requirements: { _locale: "^[a-z]{2}$" }
+
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml
index 21c0841d7554b..7660608c08dab 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/config/routing.yml
@@ -14,6 +14,17 @@ form_login_custom_target_path:
pattern: /foo
defaults: { _controller: FormLoginBundle:Login:afterLogin }
+form_login_default_target_path:
+ pattern: /profile
+ defaults: { _controller: FormLoginBundle:Login:afterLogin }
+
form_login_redirect_to_protected_resource_after_login:
pattern: /protected-resource
defaults: { _controller: FormLoginBundle:Login:afterLogin }
+
+form_logout:
+ pattern: /logout_path
+
+form_secure_action:
+ pattern: /secure-but-not-covered-by-access-control
+ defaults: { _controller: FormLoginBundle:Login:secure }
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig
new file mode 100644
index 0000000000000..60dd2f1ffac7b
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/FormLoginBundle/Resources/views/Localized/login.html.twig
@@ -0,0 +1,21 @@
+{% extends "::base.html.twig" %}
+
+{% block body %}
+
+ {% if error %}
+
{{ error.message }}
+ {% endif %}
+
+
+
+{% endblock %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
index 5f0ad8809753b..fe50eb2672b10 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/FormLoginTest.php
@@ -16,25 +16,33 @@
*/
class FormLoginTest extends WebTestCase
{
- public function testFormLogin()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testFormLogin($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $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(), '/');
+ $this->assertRedirect($client->getResponse(), '/profile');
$text = $client->followRedirect()->text();
$this->assertContains('Hello johannes!', $text);
- $this->assertContains('You\'re browsing to path "/".', $text);
+ $this->assertContains('You\'re browsing to path "/profile".', $text);
}
- public function testFormLoginWithCustomTargetPath()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testFormLoginWithCustomTargetPath($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
+ $client->insulate();
$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = 'johannes';
@@ -49,9 +57,13 @@ public function testFormLoginWithCustomTargetPath()
$this->assertContains('You\'re browsing to path "/foo".', $text);
}
- public function testFormLoginRedirectsToProtectedResourceAfterLogin()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testFormLoginRedirectsToProtectedResourceAfterLogin($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
+ $client->insulate();
$client->request('GET', '/protected-resource');
$this->assertRedirect($client->getResponse(), '/login');
@@ -67,6 +79,14 @@ public function testFormLoginRedirectsToProtectedResourceAfterLogin()
$this->assertContains('You\'re browsing to path "/protected-resource".', $text);
}
+ public function getConfigs()
+ {
+ return array(
+ array('config.yml'),
+ array('routes_as_path.yml'),
+ );
+ }
+
protected function setUp()
{
parent::setUp();
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php
new file mode 100644
index 0000000000000..1ad67ac5429b3
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/LocalizedRoutesAsPathTest.php
@@ -0,0 +1,71 @@
+createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml'));
+ $client->insulate();
+
+ $crawler = $client->request('GET', '/'.$locale.'/login');
+ $form = $crawler->selectButton('login')->form();
+ $form['_username'] = 'johannes';
+ $form['_password'] = 'test';
+ $client->submit($form);
+
+ $this->assertRedirect($client->getResponse(), '/'.$locale.'/profile');
+ $this->assertEquals('Profile', $client->followRedirect()->text());
+
+ $client->request('GET', '/'.$locale.'/logout');
+ $this->assertRedirect($client->getResponse(), '/'.$locale.'/');
+ $this->assertEquals('Homepage', $client->followRedirect()->text());
+ }
+
+ /**
+ * @dataProvider getLocales
+ */
+ public function testAccessRestrictedResource($locale)
+ {
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes.yml'));
+ $client->insulate();
+
+ $client->request('GET', '/'.$locale.'/secure/');
+ $this->assertRedirect($client->getResponse(), '/'.$locale.'/login');
+ }
+
+ /**
+ * @dataProvider getLocales
+ */
+ public function testAccessRestrictedResourceWithForward($locale)
+ {
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => 'localized_routes_with_forward.yml'));
+ $client->insulate();
+
+ $crawler = $client->request('GET', '/'.$locale.'/secure/');
+ $this->assertEquals(1, count($crawler->selectButton('login')), (string) $client->getResponse());
+ }
+
+ public function getLocales()
+ {
+ return array(array('en'), array('de'));
+ }
+
+ protected function setUp()
+ {
+ parent::setUp();
+
+ $this->deleteTmpDir('StandardFormLogin');
+ }
+
+ protected function tearDown()
+ {
+ parent::setUp();
+
+ $this->deleteTmpDir('StandardFormLogin');
+ }
+}
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
index d066f5aea56a0..d649d4434d300 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php
@@ -13,25 +13,37 @@
class SecurityRoutingIntegrationTest extends WebTestCase
{
- public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testRoutingErrorIsNotExposedForProtectedResourceWhenAnonymous($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
+ $client->insulate();
$client->request('GET', '/protected_resource');
$this->assertRedirect($client->getResponse(), '/login');
}
- public function testRoutingErrorIsExposedWhenNotProtected()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testRoutingErrorIsExposedWhenNotProtected($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
+ $client->insulate();
$client->request('GET', '/unprotected_resource');
- $this->assertEquals(404, $client->getResponse()->getStatusCode());
+ $this->assertEquals(404, $client->getResponse()->getStatusCode(), (string) $client->getResponse());
}
- public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights()
+ /**
+ * @dataProvider getConfigs
+ */
+ public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWithInsufficientRights($config)
{
- $client = $this->createClient(array('test_case' => 'StandardFormLogin'));
+ $client = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config));
+ $client->insulate();
$form = $client->request('GET', '/login')->selectButton('login')->form();
$form['_username'] = 'johannes';
@@ -43,6 +55,11 @@ public function testRoutingErrorIsNotExposedForProtectedResourceWhenLoggedInWith
$this->assertNotEquals(404, $client->getResponse()->getStatusCode());
}
+ public function getConfigs()
+ {
+ return array(array('config.yml'), array('routes_as_path.yml'));
+ }
+
protected function setUp()
{
parent::setUp();
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
index 953e9f08b9082..c5f4f79355898 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php
@@ -18,7 +18,7 @@ class WebTestCase extends BaseWebTestCase
{
static public function assertRedirect($response, $location)
{
- self::assertTrue($response->isRedirect());
+ self::assertTrue($response->isRedirect(), 'Response is not a redirect, got status code: '.$response->getStatusCode());
self::assertEquals('http://localhost'.$location, $response->headers->get('Location'));
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
index 7ed45efa1cb85..cd2445a6da979 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php
@@ -11,8 +11,21 @@
namespace Symfony\Bundle\SecurityBundle\Tests\Functional;
-use Symfony\Component\HttpKernel\Util\Filesystem;
+// get the autoload file
+$dir = __DIR__;
+$lastDir = null;
+while ($dir !== $lastDir) {
+ $lastDir = $dir;
+
+ if (file_exists($dir.'/autoload.php.dist')) {
+ require_once $dir.'/autoload.php.dist';
+ break;
+ }
+
+ $dir = dirname($dir);
+}
+use Symfony\Component\HttpKernel\Util\Filesystem;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\HttpKernel\Kernel;
@@ -33,10 +46,11 @@ public function __construct($testCase, $rootConfig, $environment, $debug)
}
$this->testCase = $testCase;
- if (!file_exists($filename = __DIR__.'/'.$testCase.'/'.$rootConfig)) {
- throw new \InvalidArgumentException(sprintf('The root config "%s" does not exist.', $filename));
+ $fs = new Filesystem();
+ if (!$fs->isAbsolutePath($rootConfig) && !file_exists($rootConfig = __DIR__.'/'.$testCase.'/'.$rootConfig)) {
+ throw new \InvalidArgumentException(sprintf('The root config "%s" does not exist.', $rootConfig));
}
- $this->rootConfig = $filename;
+ $this->rootConfig = $rootConfig;
parent::__construct($environment, $debug);
}
@@ -74,6 +88,16 @@ public function registerContainerConfiguration(LoaderInterface $loader)
$loader->load($this->rootConfig);
}
+ public function serialize()
+ {
+ return serialize(array($this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug()));
+ }
+
+ public function unserialize($str)
+ {
+ call_user_func_array(array($this, '__construct'), unserialize($str));
+ }
+
protected function getKernelParameters()
{
$parameters = parent::getKernelParameters();
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml
index e121c0b4d8932..f4b21982acba5 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/config.yml
@@ -21,9 +21,11 @@ security:
default:
form_login:
check_path: /login_check
+ default_target_path: /profile
anonymous: ~
access_control:
- { path: ^/unprotected_resource$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
+ - { path: ^/secure-but-not-covered-by-access-control$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/highly_protected_resource$, roles: IS_ADMIN }
- { path: .*, roles: IS_AUTHENTICATED_FULLY }
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes.yml
new file mode 100644
index 0000000000000..291cd2051bf21
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes.yml
@@ -0,0 +1,26 @@
+imports:
+ - { resource: ./../config/default.yml }
+
+security:
+ encoders:
+ Symfony\Component\Security\Core\User\User: plaintext
+
+ providers:
+ in_memory:
+ users:
+ johannes: { password: test, roles: [ROLE_USER] }
+
+ firewalls:
+ default:
+ form_login:
+ login_path: localized_login_path
+ check_path: localized_check_path
+ default_target_path: localized_default_target_path
+ logout:
+ path: localized_logout_path
+ target: localized_logout_target_path
+ anonymous: ~
+
+ access_control:
+ - { path: '^/(?:[a-z]{2})/secure/.*', roles: ROLE_USER }
+
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes_with_forward.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes_with_forward.yml
new file mode 100644
index 0000000000000..d57f84e8efb25
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/localized_routes_with_forward.yml
@@ -0,0 +1,9 @@
+imports:
+ - { resource: ./localized_routes.yml }
+
+security:
+ firewalls:
+ default:
+ form_login:
+ use_forward: true
+ failure_forward: true
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routes_as_path.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routes_as_path.yml
new file mode 100644
index 0000000000000..800b8ac4e7fd5
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routes_as_path.yml
@@ -0,0 +1,13 @@
+imports:
+ - { resource: ./config.yml }
+
+security:
+ firewalls:
+ default:
+ form_login:
+ login_path: form_login
+ check_path: form_login_check
+ default_target_path: form_login_default_target_path
+ logout:
+ path: form_logout
+ target: form_login_homepage
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routing.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routing.yml
index d3d46d054b213..e4f13cf0607dc 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routing.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/StandardFormLogin/routing.yml
@@ -1,2 +1,5 @@
_form_login_bundle:
resource: @FormLoginBundle/Resources/config/routing.yml
+
+_form_login_localized:
+ resource: @FormLoginBundle/Resources/config/localized_routing.yml
\ No newline at end of file
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml
index 77e9f2241d302..4cafd76671c67 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/config/framework.yml
@@ -9,9 +9,8 @@ framework:
test: ~
session:
default_locale: en
- lifetime: 3600
auto_start: true
- storage_id: session.storage.filesystem
+ storage_id: session.storage.filesystem
services:
logger: { class: Symfony\Component\HttpKernel\Log\NullLogger }
diff --git a/src/Symfony/Component/HttpFoundation/RequestMatcher.php b/src/Symfony/Component/HttpFoundation/RequestMatcher.php
index dc5a2c34f78f4..9adf780bcc21b 100644
--- a/src/Symfony/Component/HttpFoundation/RequestMatcher.php
+++ b/src/Symfony/Component/HttpFoundation/RequestMatcher.php
@@ -100,11 +100,7 @@ public function matches(Request $request)
}
if (null !== $this->path) {
- if (null !== $session = $request->getSession()) {
- $path = strtr($this->path, array('{_locale}' => $session->getLocale(), '#' => '\\#'));
- } else {
- $path = str_replace('#', '\\#', $this->path);
- }
+ $path = str_replace('#', '\\#', $this->path);
if (!preg_match('#'.$path.'#', $request->getPathInfo())) {
return false;
diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php
index c75739080fd6f..46ffde83e6d8c 100644
--- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php
+++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php
@@ -76,6 +76,11 @@ public function onKernelException(GetResponseForExceptionEvent $event)
$exception = $event->getException();
$request = $event->getRequest();
+ // determine the actual cause for the exception
+ while (null !== $previous = $exception->getPrevious()) {
+ $exception = $previous;
+ }
+
if ($exception instanceof AuthenticationException) {
if (null !== $this->logger) {
$this->logger->info(sprintf('Authentication exception occurred; redirecting to authentication entry point (%s)', $exception->getMessage()));
diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php
index 51168cc1e37dd..3eccb4188b99b 100644
--- a/src/Symfony/Component/Security/Http/HttpUtils.php
+++ b/src/Symfony/Component/Security/Http/HttpUtils.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Security\Http;
+use Symfony\Component\Security\Core\SecurityContextInterface;
+
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
@@ -45,22 +47,10 @@ public function __construct(RouterInterface $router = null)
*/
public function createRedirectResponse(Request $request, $path, $status = 302)
{
- if (0 === strpos($path, '/')) {
+ if ('/' === $path[0]) {
$path = $request->getUriForPath($path);
} elseif (0 !== strpos($path, 'http')) {
- // hack (don't have a better solution for now)
- $context = $this->router->getContext();
- try {
- $parameters = $this->router->match($request->getPathInfo());
- } catch (\Exception $e) {
- }
-
- if (isset($parameters['_locale'])) {
- $context->setParameter('_locale', $parameters['_locale']);
- } elseif ($session = $request->getSession()) {
- $context->setParameter('_locale', $session->getLocale());
- }
-
+ $this->resetLocale($request);
$path = $this->generateUrl($path, true);
}
@@ -78,10 +68,26 @@ public function createRedirectResponse(Request $request, $path, $status = 302)
public function createRequest(Request $request, $path)
{
if ($path && '/' !== $path[0] && 0 !== strpos($path, 'http')) {
+ $this->resetLocale($request);
$path = $this->generateUrl($path, true);
}
- return Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
+ $newRequest = Request::create($path, 'get', array(), $request->cookies->all(), array(), $request->server->all());
+ if ($session = $request->getSession()) {
+ $newRequest->setSession($session);
+ }
+
+ if ($request->attributes->has(SecurityContextInterface::AUTHENTICATION_ERROR)) {
+ $newRequest->attributes->set(SecurityContextInterface::AUTHENTICATION_ERROR, $request->attributes->get(SecurityContextInterface::AUTHENTICATION_ERROR));
+ }
+ if ($request->attributes->has(SecurityContextInterface::ACCESS_DENIED_ERROR)) {
+ $newRequest->attributes->set(SecurityContextInterface::ACCESS_DENIED_ERROR, $request->attributes->get(SecurityContextInterface::ACCESS_DENIED_ERROR));
+ }
+ if ($request->attributes->has(SecurityContextInterface::LAST_USERNAME)) {
+ $newRequest->attributes->set(SecurityContextInterface::LAST_USERNAME, $request->attributes->get(SecurityContextInterface::LAST_USERNAME));
+ }
+
+ return $newRequest;
}
/**
@@ -107,6 +113,27 @@ public function checkRequestPath(Request $request, $path)
return $path === $request->getPathInfo();
}
+ // hack (don't have a better solution for now)
+ private function resetLocale(Request $request)
+ {
+ $context = $this->router->getContext();
+ if ($context->getParameter('_locale')) {
+ return;
+ }
+
+ try {
+ $parameters = $this->router->match($request->getPathInfo());
+
+ if (isset($parameters['_locale'])) {
+ $context->setParameter('_locale', $parameters['_locale']);
+ } elseif ($session = $request->getSession()) {
+ $context->setParameter('_locale', $session->getLocale());
+ }
+ } catch (\Exception $e) {
+ // let's hope user doesn't use the locale in the path
+ }
+ }
+
private function generateUrl($route, $absolute = false)
{
if (null === $this->router) {
diff --git a/tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php b/tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php
index 677c286fa8c08..d807d22893759 100644
--- a/tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php
+++ b/tests/Symfony/Tests/Component/HttpFoundation/RequestMatcherTest.php
@@ -142,7 +142,7 @@ public function testPath()
$this->assertFalse($matcher->matches($request));
}
- public function testPathWithLocale()
+ public function testPathWithLocaleIsNotSupported()
{
$matcher = new RequestMatcher();
$request = Request::create('/en/login');
@@ -152,9 +152,6 @@ public function testPathWithLocale()
$request->setSession($session);
$matcher->matchPath('^/{_locale}/login$');
- $this->assertTrue($matcher->matches($request));
-
- $session->setLocale('de');
$this->assertFalse($matcher->matches($request));
}
diff --git a/tests/Symfony/Tests/Component/Security/Http/HttpUtilsTest.php b/tests/Symfony/Tests/Component/Security/Http/HttpUtilsTest.php
index cfba0f0094d26..4bea58e8e2bb3 100644
--- a/tests/Symfony/Tests/Component/Security/Http/HttpUtilsTest.php
+++ b/tests/Symfony/Tests/Component/Security/Http/HttpUtilsTest.php
@@ -61,6 +61,17 @@ public function testCreateRequest()
$this->assertEquals('bar', $subRequest->server->get('Foo'));
// route name
+ $utils = new HttpUtils($router = $this->getMockBuilder('Symfony\Component\Routing\Router')->disableOriginalConstructor()->getMock());
+ $router
+ ->expects($this->once())
+ ->method('generate')
+ ->will($this->returnValue('/foo/bar'))
+ ;
+ $router
+ ->expects($this->any())
+ ->method('getContext')
+ ->will($this->returnValue($this->getMock('Symfony\Component\Routing\RequestContext')))
+ ;
$subRequest = $utils->createRequest($this->getRequest(), 'foobar');
$this->assertEquals('/foo/bar', $subRequest->getPathInfo());