Symfony UserInterface正在序列化整个大规模用户实体

时间:2017-02-06 17:56:45

标签: php symfony authentication serialization

我们实施AdvancedUserInterface来管理用户身份验证,但由于某些原因,Symfony安全性正在序列化整个User实体,而不仅仅是最小的必填字段(例如id,{{1} },username)。

根据documentation,我们需要指定应序列化的确切字段(然后将忽略其余字段)。

password

但是尽管我们这样做,但Symfony安全性忽略了这个class User implements AdvancedUserInterface, \Serializable { /** * @see \Serializable::serialize() */ public function serialize() { return serialize(array( $this->id, $this->username, $this->password )); } } 方法并仍然序列化了整个实体。这会破坏登录,因为对象变得太大而无法序列化和存储。

2 个答案:

答案 0 :(得分:1)

显然,Symfony安全性使用Symfony\Component\Security\Core\Authentication\Token\AbstractToken,这有一个自定义序列化方法,可以将更多数据添加到会话序列化用户中。

public function serialize()
{
    return serialize(
        array(
            is_object($this->user) ? clone $this->user : $this->user,
            $this->authenticated,
            $this->roles,
            $this->attributes,
        )
    );
}

这会将role添加到序列化对象。但是我们有一个自定义角色系统,它与其他实体(例如Site)有关联,导致User在序列化时导致致命的膨胀。

答案 1 :(得分:0)

我意识到这是一个老问题,但我使用带有组的 Symfony 序列化程序解决了一个类似的问题。您可以阅读有关此 here 的更多信息。

对组进行编码的函数如下所示:

 public static function encodeCategory($objects)
{
    $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));

    $encoders = [new JsonEncoder()];
    $defaultContext = [
        AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
            if(method_exists($object,'getName'))
                return $object->getName();
        },
    ];

    $normalizers = [new ObjectNormalizer($classMetadataFactory, null, null, null, null, null, $defaultContext)];
    $serializer = new Serializer($normalizers,$encoders);

    return $serializer->serialize($objects,'json',['groups' => 'category']);
}

一个简单的实体示例如下:

class User 
{

    /**
    * @ORM\Id()
    * @ORM\GeneratedValue()
    * @ORM\Column(type="integer")
    * @Groups({"category"})
    */
    private $id;

    /**
    * @ORM\Column(type="string", length=255)
    * @Groups({"category"})
    */
    private $name;

    /**
    * @ORM\ManyToOne(targetEntity="App\Entity\Type", inversedBy="users")
    * @ORM\JoinColumn(nullable=false)
    * @Groups({"category"})
    */
    private $type;
}

和类型实体:

class Type 
{
    /**
    * @ORM\Id()
    * @ORM\GeneratedValue()
    * @ORM\Column(type="integer")
    * @Groups({"category"})
    */
    private $id;

    /**
    * @ORM\Column(type="string", length=255)
    * @Groups({"category"})
    */
    private $name;

    /**
    * @ORM\OneToMany(targetEntity="App\Entity\User", mappedBy="type")
    */
    private $users;
}

您可以为任意数量的实体扩展此功能,或创建新组。现在使用该功能:

$users = $this->getDoctrine()->getRepository(User::class)->findAll();
return new JsonResponse($this->encodeCategory($users));

在使用组之前,我尝试了 MaxDepth 注释,但它似乎有 some problems