A few months ago, Iltar van der Berg commented on one of his amazing blog posts about the security problems that are in Symfony’s Security component. Well, not a security problem, but rather something that is totally unnecessary to implement while programming with the Security component.
According to Symfony’s official documentation, the entity provider page, it is a standard to bind the UserInterface to the User entity class. This results in the following result: The complete user entity is the session and you will probably also use the entity in a form. According to Iltar’s blog post, which I fully agree with, you get synchronization issues.
If you update your entity, that means your session entity won’t be updated as it’s not from the database. In order to solve this issue, you can merge the entity back into the entity manager on each request.
While this solves one of the problems, another common issue is the (un)serialization. Eventually your User Entity will get relations to other objects and this comes with several side-effects: the relations will be serialized as well and if a relation is lazy loaded (standard setting), it will try to serialize the Proxy which contains a connection. This will spew some errors on your screen as the connection cannot be serialized and don’t even think about changing your Entity such as adding fields, this will cause unserialization issues with incomplete objects because of missing properties. This case is triggered for every authenticated user.
Iltar’s complete blog post explains why you should follow his method. To summarize, I will publish the source code for the sake of completeness, which will make it useful for you. The object below sole responsibility is to feed the security system with only the information required. The sole responsibility of this object is to implement the UserInterface and provide the security system with authentication:
According to the documentation, you have to implement an interface which will return an object implementing the UserInterface: the Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface. In the example this is done by adding it to your UserRepository, which is a doctrine EntityRepository. Considering your UserRepository must return User entities, you can’t simply make it return a SecurityUser. To solve this, you have to make an object using the UserRepository creating a SecurityUser:
You will also need to add the following services to your application to make this runnable:
To conclude, the entity is not longer stored in the session, avoiding synchronization and serialization issues. It also makes the entity and repository not longer tightly coupled to the security system and the SecurityAccount now only contains data required for identification.