mirror of
https://github.com/symfony/maker-bundle.git
synced 2026-03-23 23:42:10 +01:00
[make:user] Hash passwords using crc32c and deprecate eraseCredentials()
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
"symfony/http-client": "^6.4|^7.0",
|
||||
"symfony/phpunit-bridge": "^6.4.1|^7.0",
|
||||
"symfony/security-core": "^6.4|^7.0",
|
||||
"symfony/security-http": "^6.4|^7.0",
|
||||
"symfony/yaml": "^6.4|^7.0",
|
||||
"twig/twig": "^3.0|^4.x-dev"
|
||||
},
|
||||
|
||||
@@ -17,6 +17,7 @@ use Symfony\Bundle\MakerBundle\Util\ClassSource\Model\ClassProperty;
|
||||
use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator;
|
||||
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGrantedContext;
|
||||
|
||||
/**
|
||||
* Adds logic to implement UserInterface to an existing User class.
|
||||
@@ -37,7 +38,13 @@ final class UserClassBuilder
|
||||
|
||||
$this->addPasswordImplementation($manipulator, $userClassConfig);
|
||||
|
||||
$this->addEraseCredentials($manipulator);
|
||||
if (class_exists(IsGrantedContext::class)) {
|
||||
$this->addSerialize($manipulator);
|
||||
}
|
||||
|
||||
if (method_exists(UserInterface::class, 'eraseCredentials')) {
|
||||
$this->addEraseCredentials($manipulator);
|
||||
}
|
||||
}
|
||||
|
||||
private function addPasswordImplementation(ClassSourceManipulator $manipulator, UserClassConfiguration $userClassConfig): void
|
||||
@@ -245,17 +252,80 @@ final class UserClassBuilder
|
||||
$builder = $manipulator->createMethodBuilder(
|
||||
'eraseCredentials',
|
||||
'void',
|
||||
false,
|
||||
['@see UserInterface']
|
||||
false
|
||||
);
|
||||
$builder->addAttribute(new Node\Attribute(new Node\Name('\Deprecated')));
|
||||
$builder->addStmt(
|
||||
$manipulator->createMethodLevelCommentNode(
|
||||
'If you store any temporary, sensitive data on the user, clear it here'
|
||||
'@deprecated, to be removed when upgrading to Symfony 8'
|
||||
)
|
||||
);
|
||||
|
||||
$manipulator->addMethodBuilder($builder);
|
||||
}
|
||||
|
||||
private function addSerialize(ClassSourceManipulator $manipulator): void
|
||||
{
|
||||
$builder = $manipulator->createMethodBuilder(
|
||||
'__serialize',
|
||||
'array',
|
||||
false,
|
||||
[
|
||||
'Ensure the session doesn\'t contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.',
|
||||
]
|
||||
);
|
||||
|
||||
// $data = (array) $this;
|
||||
$builder->addStmt(
|
||||
$manipulator->createMethodLevelCommentNode(
|
||||
'$this->plainPassword = null;'
|
||||
new Node\Stmt\Expression(
|
||||
new Node\Expr\Assign(
|
||||
new Node\Expr\Variable('data'),
|
||||
new Node\Expr\Cast\Array_(
|
||||
new Node\Expr\Variable('this')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// $data["\0".self::class."\0password"] = hash('crc32c', $this->password);
|
||||
$builder->addStmt(
|
||||
new Node\Stmt\Expression(
|
||||
new Node\Expr\Assign(
|
||||
new Node\Expr\ArrayDimFetch(
|
||||
new Node\Expr\Variable('data'),
|
||||
new Node\Expr\BinaryOp\Concat(
|
||||
new Node\Expr\BinaryOp\Concat(
|
||||
new Node\Scalar\String_("\0", ['kind' => Node\Scalar\String_::KIND_DOUBLE_QUOTED]),
|
||||
new Node\Expr\ClassConstFetch(
|
||||
new Node\Name('self'),
|
||||
'class'
|
||||
)
|
||||
),
|
||||
new Node\Scalar\String_("\0password", ['kind' => Node\Scalar\String_::KIND_DOUBLE_QUOTED]),
|
||||
)
|
||||
),
|
||||
new Node\Expr\FuncCall(
|
||||
new Node\Name('hash'),
|
||||
[
|
||||
new Node\Arg(new Node\Scalar\String_('crc32c')),
|
||||
new Node\Arg(
|
||||
new Node\Expr\PropertyFetch(
|
||||
new Node\Expr\Variable('this'),
|
||||
'password'
|
||||
)
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$builder->addStmt(new Node\Stmt\Nop());
|
||||
|
||||
// return $data;
|
||||
$builder->addStmt(
|
||||
new Node\Stmt\Return_(
|
||||
new Node\Expr\Variable('data')
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ final class PrettyPrinter extends Standard
|
||||
if ($node->returnType) {
|
||||
$classMethod = str_replace(') :', '):', $classMethod);
|
||||
}
|
||||
$classMethod = str_replace('\x00', '\0', $classMethod);
|
||||
|
||||
return $classMethod;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,8 @@ use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bundle\MakerBundle\Security\UserClassBuilder;
|
||||
use Symfony\Bundle\MakerBundle\Security\UserClassConfiguration;
|
||||
use Symfony\Bundle\MakerBundle\Util\ClassSourceManipulator;
|
||||
use Symfony\Component\Security\Core\User\UserInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGrantedContext;
|
||||
|
||||
class UserClassBuilderTest extends TestCase
|
||||
{
|
||||
@@ -31,6 +33,14 @@ class UserClassBuilderTest extends TestCase
|
||||
$expectedPath = $this->getExpectedPath($expectedFilename, null);
|
||||
$expectedSource = file_get_contents($expectedPath);
|
||||
|
||||
if (!class_exists(IsGrantedContext::class)) {
|
||||
$expectedSource = preg_replace('/\n\n(.+\n)+.+function __serialize[^}]++}/', '', $expectedSource);
|
||||
}
|
||||
|
||||
if (!method_exists(UserInterface::class, 'eraseCredentials')) {
|
||||
$expectedSource = preg_replace('/\n\n(.+\n)+.+function eraseCredentials[^}]++}/', '', $expectedSource);
|
||||
}
|
||||
|
||||
self::assertSame($expectedSource, $manipulator->getSourceCode());
|
||||
}
|
||||
|
||||
|
||||
@@ -96,11 +96,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,11 +91,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,11 +91,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,19 @@ class User implements UserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,11 +80,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,11 +75,19 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,11 +54,19 @@ class User implements UserInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @see UserInterface
|
||||
* Ensure the session doesn't contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3.
|
||||
*/
|
||||
public function __serialize(): array
|
||||
{
|
||||
$data = (array) $this;
|
||||
$data["\0" . self::class . "\0password"] = hash('crc32c', $this->password);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
#[\Deprecated]
|
||||
public function eraseCredentials(): void
|
||||
{
|
||||
// If you store any temporary, sensitive data on the user, clear it here
|
||||
// $this->plainPassword = null;
|
||||
// @deprecated, to be removed when upgrading to Symfony 8
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user