【发布时间】:2021-01-29 20:26:55
【问题描述】:
-
信息:我是 Symfony 和 Sonata 的新手
-
我的目标:只为数据库端加密密码。我将能够清楚地显示此密码。所有这些都适用于实体 Service 中的字段 password。
-
我在尝试什么? : 我尝试创建一个使用
bcrypt加密的 Doctrine Listener安全性:
编码器: 应用\实体\服务:bcrypt
-
这是我的 App\Doctrine 中的 HashPasswordLisetener.php(在 App\Admin\ServiceAdmin.php 的 configureFormField 函数的 $formMapper 中,我有这样一行 ->add('password'))
<?php
namespace App\Doctrine;
use App\Entity\Service;
use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class HashPasswordListener implements EventSubscriber
{
private $passwordEncoder;
public function __construct(UserPasswordEncoderInterface $passwordEncoder)
{
$this->passwordEncoder = $passwordEncoder;
}
public function prePersist(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!$entity instanceof Service) {
return;
}
$this->encodePassword($entity);
}
public function preUpdate(LifecycleEventArgs $args)
{
$entity = $args->getEntity();
if (!$entity instanceof Service) {
return;
}
$this->encodePassword($entity);
$em = $args->getEntityManager();
$meta = $em->getClassMetadata(get_class($entity));
$em->getUnitOfWork()->recomputeSingleEntityChangeSet($meta, $entity);
}
public function getSubscribedEvents()
{
return ['prePersist', 'preUpdate'];
}
/**
* @param Service $entity
*/
private function encodePassword(Service $entity)
{
if (!$entity->getPlainPassword()) {
return;
}
$encoded = $this->passwordEncoder->encodePassword(
$entity,
$entity->getPlainPassword()
);
$entity->setPassword($encoded);
}
}
这里是 App\Entity 中的 Service 实体
<?php
namespace App\Entity;
use App\Admin\AbstractAdmin;
use App\Repository\ServiceRepository;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Entity(repositoryClass=ServiceRepository::class)
*/
class Service implements UserInterface
{
use TimestampableEntity;
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
/**
* @ORM\Column(type="string", length=255)
*/
private $password;
/**
* @ORM\Column(type="text", nullable=true, length=255)
*/
private $comment;
/**
* @ORM\Column(type="string", length=255)
*/
private $identifier;
private $plainPassword;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getComment(): ?string
{
return $this->comment;
}
public function setComment(?string $comment): self
{
$this->comment = $comment;
return $this;
}
public function getIdentifier(): ?string
{
return $this->identifier;
}
public function setIdentifier(string $identifier): self
{
$this->identifier = $identifier;
return $this;
}
/**
* @return mixed
*/
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* @param mixed $plainPassword
*/
public function setPlainPassword($plainPassword): void
{
$this->plainPassword = $plainPassword;
$this->password = null;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function getSalt()
{
}
public function eraseCredentials()
{
$this->plainPassword = null;
}
public function getUsername()
{
return $this->identifier;
}
}
还有我的 sonata_admin.yaml :
app.doctrine.hash_password_listener:
class: App\Doctrine\HashPasswordListener
autowire : true
tags:
- { name: doctrine.event_subscriber, connection: 'default' }
-
我的问题: 我知道函数 encodePassword 正在等待第一个参数(而不是我的实体)中的 UserInterface 和第二个参数中要加密的密码,但我不明白谁使用这个 UserInterface ?我应该在哪里称呼它?为拿到它,为实现它 ?发送它?
我想我提供了很多细节,但如果我忘记了什么,请随时注意我^^ 感谢您至少花时间阅读。
【问题讨论】:
-
UserInterface用于整个auth system。只需让您的Service实体实现它。但如果你不想,你可以用PasswordEncoder代替UserPasswordEncoder,见EncoderFactory。 -
好的,我会试试的
-
像以前一样输入
UserPasswordEncoderInterface。 -
这不一定是
username字段,只是一种唯一标识用户帐户的方法。我猜在您的情况下,只需删除abstract关键字并将其设为return $this->identifier;。 -
您确定正在调用侦听器吗?另一方面,
setPassword只能由侦听器调用,应该无法在其中得到明文密码,您的表单映射是否正确?
标签: symfony doctrine-orm doctrine password-encryption sonata