1717use Symfony \Bundle \MakerBundle \Util \ClassSourceManipulator ;
1818use Symfony \Component \Security \Core \User \PasswordAuthenticatedUserInterface ;
1919use Symfony \Component \Security \Core \User \UserInterface ;
20+ use Symfony \Component \Security \Http \Attribute \IsGrantedContext ;
2021
2122/**
2223 * Adds logic to implement UserInterface to an existing User class.
@@ -37,7 +38,13 @@ public function addUserInterfaceImplementation(ClassSourceManipulator $manipulat
3738
3839 $ this ->addPasswordImplementation ($ manipulator , $ userClassConfig );
3940
40- $ this ->addEraseCredentials ($ manipulator );
41+ if (class_exists (IsGrantedContext::class)) {
42+ $ this ->addSerialize ($ manipulator );
43+ }
44+
45+ if (method_exists (UserInterface::class, 'eraseCredentials ' )) {
46+ $ this ->addEraseCredentials ($ manipulator );
47+ }
4148 }
4249
4350 private function addPasswordImplementation (ClassSourceManipulator $ manipulator , UserClassConfiguration $ userClassConfig ): void
@@ -245,17 +252,80 @@ private function addEraseCredentials(ClassSourceManipulator $manipulator): void
245252 $ builder = $ manipulator ->createMethodBuilder (
246253 'eraseCredentials ' ,
247254 'void ' ,
248- false ,
249- ['@see UserInterface ' ]
255+ false
250256 );
257+ $ builder ->addAttribute (new Node \Attribute (new Node \Name ('\Deprecated ' )));
251258 $ builder ->addStmt (
252259 $ manipulator ->createMethodLevelCommentNode (
253- 'If you store any temporary, sensitive data on the user, clear it here '
260+ '@deprecated, to be removed when upgrading to Symfony 8 '
254261 )
255262 );
263+
264+ $ manipulator ->addMethodBuilder ($ builder );
265+ }
266+
267+ private function addSerialize (ClassSourceManipulator $ manipulator ): void
268+ {
269+ $ builder = $ manipulator ->createMethodBuilder (
270+ '__serialize ' ,
271+ 'array ' ,
272+ false ,
273+ [
274+ 'Ensure the session doesn \'t contain actual password hashes by CRC32C-hashing them, as supported since Symfony 7.3. ' ,
275+ ]
276+ );
277+
278+ // $data = (array) $this;
256279 $ builder ->addStmt (
257- $ manipulator ->createMethodLevelCommentNode (
258- '$this->plainPassword = null; '
280+ new Node \Stmt \Expression (
281+ new Node \Expr \Assign (
282+ new Node \Expr \Variable ('data ' ),
283+ new Node \Expr \Cast \Array_ (
284+ new Node \Expr \Variable ('this ' )
285+ )
286+ )
287+ )
288+ );
289+
290+ // $data["\0".self::class."\0password"] = hash('crc32c', $this->password);
291+ $ builder ->addStmt (
292+ new Node \Stmt \Expression (
293+ new Node \Expr \Assign (
294+ new Node \Expr \ArrayDimFetch (
295+ new Node \Expr \Variable ('data ' ),
296+ new Node \Expr \BinaryOp \Concat (
297+ new Node \Expr \BinaryOp \Concat (
298+ new Node \Scalar \String_ ("\0" , ['kind ' => Node \Scalar \String_::KIND_DOUBLE_QUOTED ]),
299+ new Node \Expr \ClassConstFetch (
300+ new Node \Name ('self ' ),
301+ 'class '
302+ )
303+ ),
304+ new Node \Scalar \String_ ("\0password " , ['kind ' => Node \Scalar \String_::KIND_DOUBLE_QUOTED ]),
305+ )
306+ ),
307+ new Node \Expr \FuncCall (
308+ new Node \Name ('hash ' ),
309+ [
310+ new Node \Arg (new Node \Scalar \String_ ('crc32c ' )),
311+ new Node \Arg (
312+ new Node \Expr \PropertyFetch (
313+ new Node \Expr \Variable ('this ' ),
314+ 'password '
315+ )
316+ ),
317+ ]
318+ )
319+ )
320+ )
321+ );
322+
323+ $ builder ->addStmt (new Node \Stmt \Nop ());
324+
325+ // return $data;
326+ $ builder ->addStmt (
327+ new Node \Stmt \Return_ (
328+ new Node \Expr \Variable ('data ' )
259329 )
260330 );
261331
0 commit comments