bug #9806 [Security] Fix parent serialization of user object (ddeboer)

This PR was submitted for the 2.2 branch but it was merged into the 2.3 branch instead (closes #9806).

Discussion
----------

[Security] Fix parent serialization of user object

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets |
| License       | MIT
| Doc PR        |

`parent::serialize()` and `parent::unserialize()`, which are used in the `AbstractToken` are [problematic](https://bugs.php.net/bug.php?id=62836) in PHP >= 5.4. [Cloning the object](https://gist.github.com/aurelijus/4713758) before serialization seems to fix this.

Commits
-------

e0bb891 [Security] Fix parent serialization of user object
This commit is contained in:
Fabien Potencier 2013-12-23 16:46:26 +01:00
commit 50c39b946b
2 changed files with 49 additions and 1 deletions

View File

@ -146,7 +146,14 @@ abstract class AbstractToken implements TokenInterface
*/
public function serialize()
{
return serialize(array($this->user, $this->authenticated, $this->roles, $this->attributes));
return serialize(
array(
is_object($this->user) ? clone $this->user : $this->user,
$this->authenticated,
$this->roles,
$this->attributes
)
);
}
/**

View File

@ -11,7 +11,9 @@
namespace Symfony\Component\Security\Tests\Core\Authentication\Token;
use Symfony\Component\Security\Core\Authentication\Token\AbstractToken;
use Symfony\Component\Security\Core\Role\Role;
use Symfony\Component\Security\Core\Role\SwitchUserRole;
class TestUser
{
@ -28,6 +30,31 @@ class TestUser
}
}
class ConcreteToken extends AbstractToken
{
private $credentials = 'credentials_value';
public function __construct($user, array $roles = array())
{
parent::__construct($roles);
$this->setUser($user);
}
public function serialize()
{
return serialize(array($this->credentials, parent::serialize()));
}
public function unserialize($serialized)
{
list($this->credentials, $parentStr) = unserialize($serialized);
parent::unserialize($parentStr);
}
public function getCredentials() {}
}
class AbstractTokenTest extends \PHPUnit_Framework_TestCase
{
public function testGetUsername()
@ -71,6 +98,20 @@ class AbstractTokenTest extends \PHPUnit_Framework_TestCase
$this->assertEquals($token->getAttributes(), $uToken->getAttributes());
}
public function testSerializeParent()
{
$user = new TestUser('fabien');
$token = new ConcreteToken($user, array('ROLE_FOO'));
$parentToken = new ConcreteToken($user, array(new SwitchUserRole('ROLE_PREVIOUS', $token)));
$uToken = unserialize(serialize($parentToken));
$this->assertEquals(
current($parentToken->getRoles())->getSource()->getUser(),
current($uToken->getRoles())->getSource()->getUser()
);
}
/**
* @covers Symfony\Component\Security\Core\Authentication\Token\AbstractToken::__construct
*/