Added the possibility to set cookies with the same name for different domains and paths for Symfony\Component\HttpFoundation\ResponseHeaderBag
ResponseHeaderBag::hasCookie() and ResponseHeaderBag::getCookie() were removed
This commit is contained in:
parent
f08eeb4433
commit
f91f4dda13
@ -18,6 +18,9 @@ namespace Symfony\Component\HttpFoundation;
|
||||
*/
|
||||
class ResponseHeaderBag extends HeaderBag
|
||||
{
|
||||
const COOKIES_FLAT = 'flat';
|
||||
const COOKIES_ARRAY = 'array';
|
||||
|
||||
protected $computedCacheControl = array();
|
||||
protected $cookies = array();
|
||||
|
||||
@ -41,7 +44,7 @@ class ResponseHeaderBag extends HeaderBag
|
||||
public function __toString()
|
||||
{
|
||||
$cookies = '';
|
||||
foreach ($this->cookies as $cookie) {
|
||||
foreach ($this->getCookies() as $cookie) {
|
||||
$cookies .= 'Set-Cookie: '.$cookie."\r\n";
|
||||
}
|
||||
|
||||
@ -111,59 +114,61 @@ class ResponseHeaderBag extends HeaderBag
|
||||
*/
|
||||
public function setCookie(Cookie $cookie)
|
||||
{
|
||||
$this->cookies[$cookie->getName()] = $cookie;
|
||||
$this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a cookie from the array, but does not unset it in the browser
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $path
|
||||
* @param string $domain
|
||||
* @return void
|
||||
*/
|
||||
public function removeCookie($name)
|
||||
public function removeCookie($name, $path = null, $domain = null)
|
||||
{
|
||||
unset($this->cookies[$name]);
|
||||
}
|
||||
unset($this->cookies[$domain][$path][$name]);
|
||||
|
||||
/**
|
||||
* Whether the array contains any cookie with this name
|
||||
*
|
||||
* @param string $name
|
||||
* @return Boolean
|
||||
*/
|
||||
public function hasCookie($name)
|
||||
{
|
||||
return isset($this->cookies[$name]);
|
||||
}
|
||||
if (empty($this->cookies[$domain][$path])) {
|
||||
unset($this->cookies[$domain][$path]);
|
||||
|
||||
/**
|
||||
* Returns a cookie
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @throws \InvalidArgumentException When the cookie does not exist
|
||||
*
|
||||
* @return Cookie
|
||||
*/
|
||||
public function getCookie($name)
|
||||
{
|
||||
if (!$this->hasCookie($name)) {
|
||||
throw new \InvalidArgumentException(sprintf('There is no cookie with name "%s".', $name));
|
||||
if (empty($this->cookies[$domain])) {
|
||||
unset($this->cookies[$domain]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->cookies[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with all cookies
|
||||
*
|
||||
* @param string $format
|
||||
*
|
||||
* @throws \InvalidArgumentException When the $format is invalid
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getCookies()
|
||||
public function getCookies($format = 'flat')
|
||||
{
|
||||
if (!in_array($format, array(static::COOKIES_FLAT, static::COOKIES_ARRAY))) {
|
||||
throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(static::COOKIES_FLAT, static::COOKIES_ARRAY))));
|
||||
}
|
||||
|
||||
if (static::COOKIES_ARRAY === $format) {
|
||||
return $this->cookies;
|
||||
}
|
||||
|
||||
$return = array();
|
||||
foreach ($this->cookies as $path) {
|
||||
foreach ($path as $cookies) {
|
||||
foreach ($cookies as $cookie) {
|
||||
$return[] = $cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a cookie in the browser
|
||||
*
|
||||
|
@ -75,4 +75,47 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertContains("Set-Cookie: foo=deleted; expires=".gmdate("D, d-M-Y H:i:s T", time() - 31536001)."; httponly", explode("\r\n", $bag->__toString()));
|
||||
}
|
||||
|
||||
public function testCookiesWithSameNames()
|
||||
{
|
||||
$bag = new ResponseHeaderBag();
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo'));
|
||||
$bag->setCookie(new Cookie('foo', 'bar'));
|
||||
|
||||
$this->assertEquals(4, count($bag->getCookies()));
|
||||
|
||||
$headers = explode("\r\n", $bag->__toString());
|
||||
$this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers);
|
||||
$this->assertContains("Set-Cookie: foo=bar; path=/path/foo; domain=foo.bar; httponly", $headers);
|
||||
$this->assertContains("Set-Cookie: foo=bar; path=/path/bar; domain=bar.foo; httponly", $headers);
|
||||
$this->assertContains("Set-Cookie: foo=bar; path=/; httponly", $headers);
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertTrue(isset($cookies['foo.bar']['/path/foo']['foo']));
|
||||
$this->assertTrue(isset($cookies['foo.bar']['/path/bar']['foo']));
|
||||
$this->assertTrue(isset($cookies['bar.foo']['/path/bar']['foo']));
|
||||
$this->assertTrue(isset($cookies['']['/']['foo']));
|
||||
}
|
||||
|
||||
public function testRemoveCookie()
|
||||
{
|
||||
$bag = new ResponseHeaderBag();
|
||||
$bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar'));
|
||||
$bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar'));
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertTrue(isset($cookies['foo.bar']['/path/foo']));
|
||||
|
||||
$bag->removeCookie('foo', '/path/foo', 'foo.bar');
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertFalse(isset($cookies['foo.bar']['/path/foo']));
|
||||
|
||||
$bag->removeCookie('bar', '/path/bar', 'foo.bar');
|
||||
|
||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertFalse(isset($cookies['foo.bar']));
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Tests\Component\Security\Http\Logout;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Security\Http\Logout\CookieClearingLogoutHandler;
|
||||
|
||||
@ -25,20 +26,21 @@ class CookieClearingLogoutHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$handler = new CookieClearingLogoutHandler(array('foo' => array('path' => '/foo', 'domain' => 'foo.foo'), 'foo2' => array('path' => null, 'domain' => null)));
|
||||
|
||||
$this->assertFalse($response->headers->hasCookie('foo'));
|
||||
$cookies = $response->headers->getCookies();
|
||||
$this->assertEquals(0, count($cookies));
|
||||
|
||||
$handler->logout($request, $response, $token);
|
||||
|
||||
$cookies = $response->headers->getCookies();
|
||||
$cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$this->assertEquals(2, count($cookies));
|
||||
|
||||
$cookie = $cookies['foo'];
|
||||
$cookie = $cookies['foo.foo']['/foo']['foo'];
|
||||
$this->assertEquals('foo', $cookie->getName());
|
||||
$this->assertEquals('/foo', $cookie->getPath());
|
||||
$this->assertEquals('foo.foo', $cookie->getDomain());
|
||||
$this->assertTrue($cookie->isCleared());
|
||||
|
||||
$cookie = $cookies['foo2'];
|
||||
$cookie = $cookies['']['']['foo2'];
|
||||
$this->assertStringStartsWith('foo2', $cookie->getName());
|
||||
$this->assertNull($cookie->getPath());
|
||||
$this->assertNull($cookie->getDomain());
|
||||
|
@ -19,6 +19,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices;
|
||||
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\CookieTheftException;
|
||||
@ -281,11 +282,13 @@ class PersistentTokenBasedRememberMeServicesTest extends \PHPUnit_Framework_Test
|
||||
;
|
||||
$service->setTokenProvider($tokenProvider);
|
||||
|
||||
$this->assertFalse($response->headers->hasCookie('foo'));
|
||||
$cookies = $response->headers->getCookies();
|
||||
$this->assertEquals(0, count($cookies));
|
||||
|
||||
$service->loginSuccess($request, $response, $token);
|
||||
|
||||
$cookie = $response->headers->getCookie('foo');
|
||||
$cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$cookie = $cookies['myfoodomain.foo']['/foo/path']['foo'];
|
||||
$this->assertFalse($cookie->isCleared());
|
||||
$this->assertTrue($cookie->isSecure());
|
||||
$this->assertTrue($cookie->isHttpOnly());
|
||||
|
@ -19,6 +19,7 @@ use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
|
||||
use Symfony\Component\Security\Core\Authentication\RememberMe\PersistentToken;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices;
|
||||
use Symfony\Component\Security\Core\Exception\TokenNotFoundException;
|
||||
use Symfony\Component\Security\Core\Exception\CookieTheftException;
|
||||
@ -184,11 +185,13 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
||||
->will($this->returnValue('foo'))
|
||||
;
|
||||
|
||||
$this->assertFalse($response->headers->hasCookie('foo'));
|
||||
$cookies = $response->headers->getCookies();
|
||||
$this->assertEquals(0, count($cookies));
|
||||
|
||||
$service->loginSuccess($request, $response, $token);
|
||||
|
||||
$this->assertFalse($response->headers->hasCookie('foo'));
|
||||
$cookies = $response->headers->getCookies();
|
||||
$this->assertEquals(0, count($cookies));
|
||||
}
|
||||
|
||||
public function testLoginSuccess()
|
||||
@ -215,11 +218,13 @@ class TokenBasedRememberMeServicesTest extends \PHPUnit_Framework_TestCase
|
||||
->will($this->returnValue($user))
|
||||
;
|
||||
|
||||
$this->assertFalse($response->headers->hasCookie('foo'));
|
||||
$cookies = $response->headers->getCookies();
|
||||
$this->assertEquals(0, count($cookies));
|
||||
|
||||
$service->loginSuccess($request, $response, $token);
|
||||
|
||||
$cookie = $response->headers->getCookie('foo');
|
||||
$cookies = $response->headers->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||
$cookie = $cookies['myfoodomain.foo']['/foo/path']['foo'];
|
||||
$this->assertFalse($cookie->isCleared());
|
||||
$this->assertTrue($cookie->isSecure());
|
||||
$this->assertTrue($cookie->isHttpOnly());
|
||||
|
Reference in New Issue
Block a user