我们实施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
));
}
}
方法并仍然序列化了整个实体。这会破坏登录,因为对象变得太大而无法序列化和存储。
答案 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。