diff --git a/UPGRADE-4.3.md b/UPGRADE-4.3.md index bee2a00302..5f3bd82dcb 100644 --- a/UPGRADE-4.3.md +++ b/UPGRADE-4.3.md @@ -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 ---- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index d11420af46..58bb2035bc 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -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 -------------- diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index ac3024c481..23d3ea43be 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -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 ----- diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index e8546788d5..f879cf8a87 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -133,20 +133,67 @@ abstract class AbstractToken implements TokenInterface /** * {@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: + * + * protected function getState(): array + * { + * return [$this->childAttribute, parent::getState()]; + * } + * + * + * @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: + * + * protected function setState(array $data) + * { + * [$this->childAttribute, $parentData] = $data; + * parent::setState($parentData); + * } + * + * + * @see getState() + */ + protected function setState(array $data) + { + [$this->user, $this->authenticated, $this->roles, $this->attributes] = $data; } /** diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php index 328d3043d2..18b2481330 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php @@ -57,19 +57,17 @@ class AnonymousToken extends AbstractToken /** * {@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); } } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php index bc6c0ce522..733f29159a 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php @@ -77,19 +77,17 @@ class PreAuthenticatedToken extends AbstractToken /** * {@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); } } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php index 21a190d6b3..40daa68923 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php @@ -92,19 +92,17 @@ class RememberMeToken extends AbstractToken /** * {@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); } } diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 8a70047a48..d731906eb7 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -89,19 +89,17 @@ class UsernamePasswordToken extends AbstractToken /** * {@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); } } diff --git a/src/Symfony/Component/Security/Core/Exception/AccountStatusException.php b/src/Symfony/Component/Security/Core/Exception/AccountStatusException.php index cb91b42364..4d707c07d1 100644 --- a/src/Symfony/Component/Security/Core/Exception/AccountStatusException.php +++ b/src/Symfony/Component/Security/Core/Exception/AccountStatusException.php @@ -42,20 +42,17 @@ abstract class AccountStatusException extends AuthenticationException /** * {@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); } } diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php index a8989c0687..2ee412bfd1 100644 --- a/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php +++ b/src/Symfony/Component/Security/Core/Exception/AuthenticationException.php @@ -40,18 +40,67 @@ class AuthenticationException extends RuntimeException implements \Serializable /** * {@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); + } - return $this->doSerialize($serialized, \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: + * + * protected function getState(): array + * { + * return [$this->childAttribute, parent::getState()]; + * } + * + * + * @see setState() + */ + protected function getState(): array + { + return [$this->token, $this->code, $this->message, $this->file, $this->line]; + } + + /** + * 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: + * + * protected function setState(array $data) + * { + * [$this->childAttribute, $parentData] = $data; + * parent::setState($parentData); + * } + * + * + * @see getState() + */ + protected function setState(array $data) + { + [$this->token, $this->code, $this->message, $this->file, $this->line] = $data; } /** @@ -67,17 +116,6 @@ class AuthenticationException extends RuntimeException implements \Serializable 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. * diff --git a/src/Symfony/Component/Security/Core/Exception/CustomUserMessageAuthenticationException.php b/src/Symfony/Component/Security/Core/Exception/CustomUserMessageAuthenticationException.php index 5db47013d4..bd1b18eb32 100644 --- a/src/Symfony/Component/Security/Core/Exception/CustomUserMessageAuthenticationException.php +++ b/src/Symfony/Component/Security/Core/Exception/CustomUserMessageAuthenticationException.php @@ -58,20 +58,17 @@ class CustomUserMessageAuthenticationException extends AuthenticationException /** * {@inheritdoc} */ - public function serialize() + protected function getState(): array { - $serialized = [parent::serialize(true), $this->messageKey, $this->messageData]; - - return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null); + return [parent::getState(), $this->messageKey, $this->messageData]; } /** * {@inheritdoc} */ - public function unserialize($str) + protected function setState(array $data) { - list($parentData, $this->messageKey, $this->messageData) = \is_array($str) ? $str : unserialize($str); - - parent::unserialize($parentData); + [$parentData, $this->messageKey, $this->messageData] = $data; + parent::setState($parentData); } } diff --git a/src/Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php b/src/Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php index b4b8047f34..155f80e357 100644 --- a/src/Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php +++ b/src/Symfony/Component/Security/Core/Exception/UsernameNotFoundException.php @@ -49,26 +49,6 @@ class UsernameNotFoundException extends AuthenticationException $this->username = $username; } - /** - * {@inheritdoc} - */ - public function serialize() - { - $serialized = [$this->username, parent::serialize(true)]; - - return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null); - } - - /** - * {@inheritdoc} - */ - public function unserialize($str) - { - list($this->username, $parentData) = \is_array($str) ? $str : unserialize($str); - - parent::unserialize($parentData); - } - /** * {@inheritdoc} */ @@ -76,4 +56,21 @@ class UsernameNotFoundException extends AuthenticationException { return ['{{ username }}' => $this->username]; } + + /** + * {@inheritdoc} + */ + protected function getState(): array + { + return [$this->username, parent::getState()]; + } + + /** + * {@inheritdoc} + */ + protected function setState(array $data) + { + [$this->username, $parentData] = $data; + parent::setState($parentData); + } } diff --git a/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php b/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php index 1e75129c57..9e3646da45 100644 --- a/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php +++ b/src/Symfony/Component/Security/Guard/Token/PostAuthenticationGuardToken.php @@ -74,19 +74,17 @@ class PostAuthenticationGuardToken extends AbstractToken implements GuardTokenIn /** * {@inheritdoc} */ - public function serialize() + protected function getState(): array { - $serialized = [$this->providerKey, parent::serialize(true)]; - - return $this->doSerialize($serialized, \func_num_args() ? \func_get_arg(0) : null); + return [$this->providerKey, parent::getState()]; } /** * {@inheritdoc} */ - public function unserialize($serialized) + protected function setState(array $data) { - list($this->providerKey, $parentStr) = \is_array($serialized) ? $serialized : unserialize($serialized); - parent::unserialize($parentStr); + [$this->providerKey, $parentData] = $data; + parent::setState($parentData); } }