Permalink
Browse files

feature #30052 [Security] Replace serialization API (renanbr)

This PR was merged into the 4.3-dev branch.

Discussion
----------

[Security] Replace serialization API

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

New `getState()` and `setState()` methods in `AbstractToken` and `AuthenticationException` allow users to append data to the serialization payload.

It allow us to have zero impact in user land when changing the serialization engine.

Commits
-------

006c6dd makes serialize methods final
  • Loading branch information...
nicolas-grekas committed Feb 7, 2019
2 parents 974cab3 + 006c6dd commit e8c3f9e0d00ddd6cf72340c5f61fb78932a23e4c
@@ -45,6 +45,41 @@ HttpFoundation
* The `FileinfoMimeTypeGuesser` class has been deprecated,
use `Symfony\Component\Mime\FileinfoMimeTypeGuesser` instead.

Security
--------

* The `AbstractToken::serialize()`, `AbstractToken::unserialize()`,
`AuthenticationException::serialize()` and `AuthenticationException::unserialize()`
methods are now final, use `getState()` and `setState()` instead.

Before:
```php
public function serialize()
{
return [$this->myLocalVar, parent::serialize()];
}
public function unserialize($serialized)
{
[$this->myLocalVar, $parentSerialized] = unserialize($serialized);
parent::unserialize($parentSerialized);
}
```

After:
```php
protected function getState(): array
{
return [$this->myLocalVar, parent::getState()];
}
protected function setState(array $data)
{
[$this->myLocalVar, $parentData] = $data;
parent::setState($parentData);
}
```

Yaml
----

@@ -232,6 +232,37 @@ Security
* `SimpleAuthenticatorInterface`, `SimpleFormAuthenticatorInterface`, `SimplePreAuthenticatorInterface`,
`SimpleAuthenticationProvider`, `SimpleAuthenticationHandler`, `SimpleFormAuthenticationListener` and
`SimplePreAuthenticationListener` have been removed. Use Guard instead.
* `\Serializable` interface has been removed from `AbstractToken` and `AuthenticationException`,
thus `serialize()` and `unserialize()` aren't available.
Use `getState()` and `setState()` instead.

Before:
```php
public function serialize()
{
return [$this->myLocalVar, parent::serialize()];
}
public function unserialize($serialized)
{
[$this->myLocalVar, $parentSerialized] = unserialize($serialized);
parent::unserialize($parentSerialized);
}
```

After:
```php
protected function getState(): array
{
return [$this->myLocalVar, parent::getState()];
}
protected function setState(array $data)
{
[$this->myLocalVar, $parentData] = $data;
parent::setState($parentData);
}
```

SecurityBundle
--------------
@@ -1,6 +1,12 @@
CHANGELOG
=========

4.3.0
-----

* Made the `serialize()` and `unserialize()` methods of `AbstractToken` and
`AuthenticationException` final, use `getState()`/`setState()` instead

4.2.0
-----

@@ -133,20 +133,67 @@ public function eraseCredentials()
/**
* {@inheritdoc}
*
* @final since Symfony 4.3, use getState() instead
*
* @internal since Symfony 4.3, use getState() instead
*/
public function serialize()
{
$serialized = [$this->user, $this->authenticated, $this->roles, $this->attributes];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return $this->doSerialize($this->getState(), \func_num_args() ? \func_get_arg(0) : null);
}
/**
* {@inheritdoc}
*
* @final since Symfony 4.3, use setState() instead
*
* @internal since Symfony 4.3, use setState() instead
*/
public function unserialize($serialized)
{
list($this->user, $this->authenticated, $this->roles, $this->attributes) = \is_array($serialized) ? $serialized : unserialize($serialized);
$this->setState(\is_array($serialized) ? $serialized : unserialize($serialized));
}
/**
* Returns all the necessary state of the object for serialization purposes.
*
* There is no need to serialize any entry, they should be returned as-is.
* If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
* Here is an example of how to extend this method:
* <code>
* protected function getState(): array
* {
* return [$this->childAttribute, parent::getState()];
* }
* </code>
*
* @see setState()
*/
protected function getState(): array
{
return [$this->user, $this->authenticated, $this->roles, $this->attributes];
}
/**
* Restores the object state from an array given by getState().
*
* There is no need to unserialize any entry in $data, they are already ready-to-use.
* If you extend this method, keep in mind you MUST pass the parent data to its respective class.
* Here is an example of how to extend this method:
* <code>
* protected function setState(array $data)
* {
* [$this->childAttribute, $parentData] = $data;
* parent::setState($parentData);
* }
* </code>
*
* @see getState()
*/
protected function setState(array $data)
{
[$this->user, $this->authenticated, $this->roles, $this->attributes] = $data;
}
/**
@@ -57,19 +57,17 @@ public function getSecret()
/**
* {@inheritdoc}
*/
public function serialize()
protected function getState(): array
{
$serialized = [$this->secret, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return [$this->secret, parent::getState()];
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
protected function setState(array $data)
{
list($this->secret, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
[$this->secret, $parentData] = $data;
parent::setState($parentData);
}
}
@@ -77,19 +77,17 @@ public function eraseCredentials()
/**
* {@inheritdoc}
*/
public function serialize()
protected function getState(): array
{
$serialized = [$this->credentials, $this->providerKey, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return [$this->credentials, $this->providerKey, parent::getState()];
}
/**
* {@inheritdoc}
*/
public function unserialize($str)
protected function setState(array $data)
{
list($this->credentials, $this->providerKey, $parentStr) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentStr);
[$this->credentials, $this->providerKey, $parentData] = $data;
parent::setState($parentData);
}
}
@@ -92,19 +92,17 @@ public function getCredentials()
/**
* {@inheritdoc}
*/
public function serialize()
protected function getState(): array
{
$serialized = [$this->secret, $this->providerKey, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return [$this->secret, $this->providerKey, parent::getState()];
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
protected function setState(array $data)
{
list($this->secret, $this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
[$this->secret, $this->providerKey, $parentData] = $data;
parent::setState($parentData);
}
}
@@ -89,19 +89,17 @@ public function eraseCredentials()
/**
* {@inheritdoc}
*/
public function serialize()
protected function getState(): array
{
$serialized = [$this->credentials, $this->providerKey, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return [$this->credentials, $this->providerKey, parent::getState()];
}
/**
* {@inheritdoc}
*/
public function unserialize($serialized)
protected function setState(array $data)
{
list($this->credentials, $this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized);
parent::unserialize($parentStr);
[$this->credentials, $this->providerKey, $parentData] = $data;
parent::setState($parentData);
}
}
@@ -42,20 +42,17 @@ public function setUser(UserInterface $user)
/**
* {@inheritdoc}
*/
public function serialize()
protected function getState(): array
{
$serialized = [$this->user, parent::serialize(true)];
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
return [$this->user, parent::getState()];
}
/**
* {@inheritdoc}
*/
public function unserialize($str)
protected function setState(array $data)
{
list($this->user, $parentData) = \is_array($str) ? $str : unserialize($str);
parent::unserialize($parentData);
[$this->user, $parentData] = $data;
parent::setState($parentData);
}
}
@@ -40,18 +40,67 @@ public function setToken(TokenInterface $token)
/**
* {@inheritdoc}
*
* @final since Symfony 4.3, use getState() instead
*
* @internal since Symfony 4.3, use getState() instead
*/
public function serialize()
{
$serialized = [
$this->token,
$this->code,
$this->message,
$this->file,
$this->line,
];
return $this->doSerialize($this->getState(), \func_num_args() ? \func_get_arg(0) : null);
}
/**
* {@inheritdoc}
*
* @final since Symfony 4.3, use setState() instead
*
* @internal since Symfony 4.3, use setState() instead
*/
public function unserialize($serialized)
{
$this->setState(\is_array($serialized) ? $serialized : unserialize($serialized));
}
/**
* Returns all the necessary state of the object for serialization purposes.
*
* There is no need to serialize any entry, they should be returned as-is.
* If you extend this method, keep in mind you MUST guarantee parent data is present in the state.
* Here is an example of how to extend this method:
* <code>
* protected function getState(): array
* {
* return [$this->childAttribute, parent::getState()];
* }
* </code>
*
* @see setState()
*/
protected function getState(): array
{
return [$this->token, $this->code, $this->message, $this->file, $this->line];
}
return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null);
/**
* Restores the object state from an array given by getState().
*
* There is no need to unserialize any entry in $data, they are already ready-to-use.
* If you extend this method, keep in mind you MUST pass the parent data to its respective class.
* Here is an example of how to extend this method:
* <code>
* protected function setState(array $data)
* {
* [$this->childAttribute, $parentData] = $data;
* parent::setState($parentData);
* }
* </code>
*
* @see getState()
*/
protected function setState(array $data)
{
[$this->token, $this->code, $this->message, $this->file, $this->line] = $data;
}
/**
@@ -67,17 +116,6 @@ protected function doSerialize($serialized, $isCalledFromOverridingMethod)
return $isCalledFromOverridingMethod ? $serialized : serialize($serialized);
}
public function unserialize($str)
{
list(
$this->token,
$this->code,
$this->message,
$this->file,
$this->line
) = \is_array($str) ? $str : unserialize($str);
}
/**
* Message key to be used by the translation component.
*
Oops, something went wrong.

0 comments on commit e8c3f9e

Please sign in to comment.