【问题标题】:Encode password easyadmin v3编码密码easyadmin v3
【发布时间】:2021-03-30 10:57:28
【问题描述】:

我有我的用户,我可以从我的管理面板管理,我可以更改密码,但问题是在数据库中它没有加密。它在数据库中很清楚,救救你我怎么能做到,这样它就不再存在了?我给你我的用户实体以及 crud 用户我使用 easyadmin v3 和 symfony 5 包。

我的实体用户

<?php

namespace App\Entity;

use App\Repository\UserRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\UserInterface;


/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $prenom;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $nom;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $telephone;

    /**
     * @ORM\Column(type="text", nullable=true)
     */
    private $aPropos;

    /**
     * @ORM\Column(type="string", length=255, nullable=true)
     */
    private $facebook;

    /**
     * @ORM\OneToMany(targetEntity=Realisation::class, mappedBy="user", orphanRemoval=true)
     */
    private $realisations;

    public function __construct()
    {
        $this->realisations = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

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

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Returning a salt is only needed, if you are not using a modern
     * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
     *
     * @see UserInterface
     */
    public function getSalt(): ?string
    {
        return null;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function getPrenom(): ?string
    {
        return $this->prenom;
    }

    public function setPrenom(string $prenom): self
    {
        $this->prenom = $prenom;

        return $this;
    }

    public function getNom(): ?string
    {
        return $this->nom;
    }

    public function setNom(string $nom): self
    {
        $this->nom = $nom;

        return $this;
    }

    public function getTelephone(): ?string
    {
        return $this->telephone;
    }

    public function setTelephone(string $telephone): self
    {
        $this->telephone = $telephone;

        return $this;
    }

    public function getAPropos(): ?string
    {
        return $this->aPropos;
    }

    public function setAPropos(?string $aPropos): self
    {
        $this->aPropos = $aPropos;

        return $this;
    }

    public function getFacebook(): ?string
    {
        return $this->facebook;
    }

    public function setFacebook(?string $facebook): self
    {
        $this->facebook = $facebook;

        return $this;
    }

    /**
     * @return Collection|Realisation[]
     */
    public function getRealisations(): Collection
    {
        return $this->realisations;
    }

    public function addRealisation(Realisation $realisation): self
    {
        if (!$this->realisations->contains($realisation)) {
            $this->realisations[] = $realisation;
            $realisation->setUser($this);
        }

        return $this;
    }

    public function removeRealisation(Realisation $realisation): self
    {
        if ($this->realisations->removeElement($realisation)) {
            // set the owning side to null (unless already changed)
            if ($realisation->getUser() === $this) {
                $realisation->setUser(null);
            }
        }

        return $this;
    }
    public function __toString()
    {
        return $this->nom;
    }
    /* public function __toString(){
         return $this->nom;
     }*/
}

<?php

namespace App\Controller\Admin;

use App\Entity\User;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;

class UserCrudController extends AbstractCrudController
{
    public static function getEntityFqcn(): string
    {
        return User::class;
    }


    public function configureFields(string $pageName): iterable
    {
        return [
            IntegerField::new('id','ID')->onlyOnIndex(),
            TextField::new('email'),
            TextField::new('password'),
            TextField::new('nom'),
            TextField::new('telephone'),
            TextField::new('aPropos'),
            TextField::new('facebook'),
        ];
    }


}

【问题讨论】:

    标签: passwords symfony5 easyadmin


    【解决方案1】:

    这可能会有所帮助...

    <?php
    
    namespace App\Event\Subscriber;
    
    use App\Entity\BackendUser;
    use Symfony\Component\DependencyInjection\ContainerInterface;
    use Symfony\Component\EventDispatcher\EventSubscriberInterface;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
    use EasyCorp\Bundle\EasyAdminBundle\Event\BeforeEntityUpdatedEvent;
    
    class EasyAdminHooksSubscriber implements EventSubscriberInterface {
    
        /**
         * @var UserPasswordEncoderInterface
         */
        private $passwordEncoder;
    
        /**
         * @var ContainerInterface
         */
        private $container;
    
        /**
         * EasyAdminSubscriber constructor.
         *
         * @param UserPasswordEncoderInterface $passwordEncoder
         * @param ContainerInterface $container
         */
        public function __construct(UserPasswordEncoderInterface $passwordEncoder, ContainerInterface $container) {
            $this->passwordEncoder = $passwordEncoder;
            $this->container = $container;
        }
    
        public static function getSubscribedEvents(): array {
            return array(
                BeforeEntityUpdatedEvent::class => array('preUpdateEntity')
            );
        }
    
        /**
         * @param BeforeEntityUpdatedEvent $event
         *
         * @noinspection PhpUnused
         */
        public function preUpdateEntity(BeforeEntityUpdatedEvent $event) {
            $entity = $event->getEntityInstance();
    
            if($entity instanceof BackendUser) {
                $this->preUpdateBackendUser($entity);
            }
        }
    
        /**
         * @param BackendUser $be_user
         */
        private function preUpdateBackendUser(BackendUser &$be_user) {
            $plain_password = $be_user->getPlainPassword();
    
            if(!empty($plain_password)) {
                $new_password = $this->passwordEncoder->encodePassword($be_user, $plain_password);
                $be_user->setPassword($new_password);
                $be_user->setPlainPassword();
            }
        }
    }
    

    【讨论】:

    • 您必须将其添加到您的 (Backend-)User 类中:` /** * @ORM\Column(type="string", length=255, nullable=true) */ private $普通密码; `
    • 所以我必须创建一个 Events 文件夹,制作一个订阅者文件,并将您提供给我的代码放入我的后端,然后我的密码将以加密形式返回到我的数据库?
    • 如果要放到events文件夹中,则将命名空间命名空间App\Event;而不是命名空间 App\Event\Subscriber; - 我自己遇到了这个错误,否则它会起作用。
    • 我没有答案,但这个答案似乎是一种非常复杂的方式......我们可以考虑替代解决方案吗?
    【解决方案2】:

    这是我在尝试从我的网络应用程序的管理仪表板(Symfony 5.3 和 EasyAdmin v3)创建/编辑用户时发现的solution。我在 Github 上的 EasyAdmin 问题跟踪器中找到了它。

    您需要向您的 User 类添加一个纯密码字段并设置适当的 getter 和 setter 方法。

    /**
     * @var string
     */
    private $plainPassword;
    
    /**
     * @return string
     */
    public function getPlainPassword(): string
    {
        return $this->plainPassword;
    }
    

    添加事件侦听器以侦听创建/编辑表单提交事件,从提交的表单数据中提取纯密码,然后对其进行哈希处理。

    /** @var UserPasswordHasherInterface */
    private $hasher;
    
    public function createEditFormBuilder(EntityDto $entityDto, KeyValueStore $keyValueStore, AdminContext $context): FormBuilderInterface
    {
        $formBuilder = parent::createEditFormBuilder($entityDto, $keyValueStore, $context);
        $this->addEncodePasswordEventListener($formBuilder);
    
        return $formBuilder;
    }
    
    public function createNewFormBuilder(EntityDto $entityDto, KeyValueStore $formOptions, AdminContext $context): FormBuilderInterface
    {
        $formBuilder = parent::createNewFormBuilder($entityDto, $formOptions, $context);
        $this->addEncodePasswordEventListener($formBuilder);
    
        return $formBuilder;
    }
    
    /**
     * @param FormBuilderInterface $formBuilder
     */
    public function addEncodePasswordEventListener(FormBuilderInterface $formBuilder)
    {
        $formBuilder->addEventListener(FormEvents::SUBMIT, function (FormEvent $event){
            /** @var User $user */
            $user = $event->getData();
            if ($user->getPlainPassword()) {
                $user->setPassword($this->hasher->hashPassword($user, $user->getPlainPassword()));
            }
        });
    
    }
    

    那么最后你需要渲染合适的表单域。

    public function configureFields(string $pageName): iterable
    {
        return [
            # other fields
            Field::new('plainPassword', 'New Password')->onlyOnForms()
            ->setFormType(RepeatedType::class)
            ->setFormTypeOptions([
                   'type' => PasswordType::class,
                   'first_options' => ['label' => 'New password'],
                   'second_options' => ['label' => 'Repeat Password']
            ])->setRequired(true)
        ];
    }
    

    希望有人觉得这很有用。

    【讨论】:

      【解决方案3】:

      您可以在用户实体中添加纯密码字段:

      private ?string $plainPassword= '';
      public function getPlainPassword(): ?string
      {
          return $this->plainPassword;
      }
      
      public function setPlainPassword(?string $plainPassword): void
      {
          $this->plainPassword = $plainPassword;
      }
      

      在用户存储库中添加密码更新程序:

      public function setNewPassword(PasswordAuthenticatedUserInterface $user, string $plainPassword): void
      {
      
          $hashedPassword = $this->hasher->hashPassword($user, $plainPassword);
          $user->setPassword($hashedPassword);
          $this->_em->persist($user);
          $this->_em->flush();
      }
      

      并覆盖 UserCrudController 中的更新/持久方法:

      public function updateEntity(EntityManagerInterface $entityManager, $entityInstance): void
      {
          $this->updatePassword($entityInstance);
          parent::updateEntity($entityManager, $entityInstance);
      }
      
      public function persistEntity(EntityManagerInterface $entityManager, $entityInstance): void
      {
          $this->updatePassword($entityInstance);
          parent::persistEntity($entityManager, $entityInstance);
      }
      
      private function updatePassword(User $user): void
      {
          if ($user->getPlainPassword() == '') return;
          $this->userRepository->setNewPassword($user, $user->getPlainPassword());
      }
      

      它在 Symfony 5.4.2 / EasyAdmin 3.5.19 中工作

      【讨论】:

        猜你喜欢
        • 2019-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多