防止在 Symfony 会话中存储整个用户

Prevent storing entire user in Symfony session

我的应用程序正在使用 Symfony 5.4.2 并且依赖于新的 Authenticator Manager。

我最近遇到了与 session_open() 相关的内存错误。在调查时,我注意到整个用户实体都存储在会话文件中(作为 PHP serialized 字符串),以 _sf2_attributes|.

开头

所以每个相关实体也都存储在那里(每个 属性、用户购买及其详细信息,等等),这可能非常重(我有超过 100 Kb 的会话文件,这对我来说听起来很大)。

这是预期的方式吗?
有没有办法防止序列化所有用户实体属性?

您必须序列化您的用户实体class实现\Serializable接口并定义serialize , unserialize__sleep 方法,定义哪些属性将包含在会话中。使用 __sleep 您将允许只有特定属性进入序列化过程;例如:

/**
 * Usuario
 *
 * @ORM\Table(name="usuario", uniqueConstraints={@ORM\UniqueConstraint(name="usuario_username_uniq", columns={"username"})}, indexes={@ORM\Index(name="usuario_rol_idx", columns={"rol_id"}), @ORM\Index(name="usuario_nodo_idx", columns={"estructura_organizativa_id"}), @ORM\Index(name="usuario_id_publico_idx", columns={"id_publico"})})
 * @ORM\Entity(repositoryClass="App\Repository\UsuarioRepository")
 * @UniqueEntity("username", message="Ya existe un usuario con ese identificador")    
 */
class Usuario implements UserInterface, PasswordAuthenticatedUserInterface, EquatableInterface, \Serializable
{

    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="IDENTITY")
     * @ORM\SequenceGenerator(sequenceName="usuario_id_id_seq", initialValue=1, allocationSize=100)   
     */
    private $id;

    /**
     * @var string
     * 
     * @Assert\NotBlank(message="El identificador es obligatorio.")
     * @ORM\Column(name="username", type="string", unique=true, length=100, nullable=false)
     */
    private $username;

    /**
     * @var string
     * 
     * @Assert\NotBlank(message="El nombre es obligatorio.")
     * @ORM\Column(name="nombre_completo", type="string", length=255, nullable=false)
     */
    private $nombreCompleto;

    /**
     * @var string
     * 
     * @Assert\Length(
     *      min=6, 
     *      max=255,
     *      minMessage="La contraseña debe tener como mínimo {{ limit }} caracteres",
     *      maxMessage="La contraseña no puede exceder los {{ limit }} caracteres."
     * )
     * @ORM\Column(name="password", type="string", length=255, nullable=false)
     */
    private $password;

    /**
     * @var boolean
     *
     * @ORM\Column(name="activo", type="boolean", nullable=false)
     */
    private $activo;

        
    /**
     * @var type \App\Entity\Rol
     * 
     * @ORM\ManyToOne(targetEntity="Rol", fetch="EAGER")     
     * @ORM\JoinColumn(name="rol_id", referencedColumnName="id", nullable=false, onDelete="RESTRICT")
     */
    private $rol;

    

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->activo = true;           
    }

    /**
     * Set username
     *
     * @param string $username
     * @return Usuario
     */
    public function setUsername(?string $username): self
    {
        $this->username = $username;

        return $this;
    }

    /**
     * Get username
     *
     * @return string 
     */
    public function getUsername(): string
    {
        return $this->username;
    }

    /**
     * Set nombreCompleto
     *
     * @param string $nombreCompleto
     * @return Usuario
     */
    public function setNombreCompleto(string $nombreCompleto): self
    {
        $this->nombreCompleto = $nombreCompleto;

        return $this;
    }

    /**
     * Get nombreCompleto
     *
     * @return string 
     */
    public function getNombreCompleto(): string
    {
        return $this->nombreCompleto;
    }

    /**
     * 
     * @return array
     */
    public function getRoles(): array
    {
        $coleccion = new ArrayCollection();
        $coleccion->add($this->getRol()->getToken());
        $coleccion[] = "ROLE_USER";

        return array_unique($coleccion->toArray());
    }

    /**
     * Set password
     *
     * @param string $password
     * @return Usuario
     */
    public function setPassword(?string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Get password
     *
     * @return string 
     */
    public function getPassword(): string
    {
        return $this->password;
    }

    /**
     * Set activo
     *
     * @param bool $activo
     * @return Usuario
     */
    public function setActivo(bool $activo): self
    {
        $this->activo = $activo;

        return $this;
    }

    /**
     * Get activo
     *
     * @return bool 
     */
    public function getActivo(): bool
    {
        return $this->activo;
    }

    /**
     * Get id
     *
     * @return integer 
     */
    public function getId(): ?int
    {
        return $this->id;
    }

    

    /**
     * 
     * @return void
     */
    public function eraseCredentials(): void
    {
        
    }

    /**
     * 
     * @return string
     */
    public function getSalt(): string
    {
        return '';
    }

    /**
     * 
     * @return bool
     */
    public function isAccountNonExpired(): bool
    {
        return true;
    }

    /**
     * 
     * @return bool
     */
    public function isAccountNonLocked(): bool
    {
        return true;
    }

    /**
     * 
     * @return bool
     */
    public function isCredentialsNonExpired(): bool
    {
        return true;
    }

    /**
     * 
     * @return bool
     */
    public function isEnabled(): bool
    {
        return $this->activo;
    }

    /**
     * 
     * @return string
     */
    public function serialize(): string
    {
        return serialize([
            $this->username,
            $this->nombreCompleto,
            $this->password,
            $this->activo,
            $this->id,
            $this->idPublico
        ]);
    }

    /**
     * 
     * @param type $serialized
     * @return void
     */
    public function unserialize($serialized): void
    {
        list(
                $this->username,
                $this->nombreCompleto,
                $this->password,
                $this->activo,
                $this->id,
                $this->idPublico
                ) = unserialize($serialized);
    }

    /**
     * 
     * @return array
     */
    public function __sleep(): array
    {
        return ['username', 'nombreCompleto', 'password', 'activo', 'id', 'idPublico'];
    }

    /**
     * 
     * @return string
     */
    public function __toString(): string
    {
        return $this->nombreCompleto;
    }    
    

    /**
     * 
     * @param UserInterface $user
     * @return bool
     */
    public function isEqualTo(UserInterface $user): bool
    {
        if ($this->getUsername() === $user->getUsername() && $this->getPassword() === $user->getPassword() && $this->getSalt() === $user->getSalt()) {
            return true;
        }

        return false;
    }

    /**
     * @return string
     * * */
    public function getUserIdentifier(): string
    {
        return (string) $this->username;
    }

}