Symfony2 Form Encode Password on Submit

Ho creato un UserType per un object utente personalizzato. Uno dei campi è una password.

Idealmente, mi piacerebbe che codificasse la password quando invio il module come trasformatore di dati / correlato invece di whererlo gestire nel controller. Tuttavia, è una password salata, quindi questo pone un problema perché mi piace rigenerare il sale each volta che generare la password. Non conosco un modo per get questo valore in più nel mio DataTransformsr.

Quindi, fondamentalmente ho due domande:

  • È una buona o ctriggers idea far sì che faccia la codifica come parte di UserType (AbstractType), o dovrei gestirlo nel Controller?
  • Come posso passare le informazioni richieste al mio DataTransformsr per renderlo ansible?

Grazie.

Così, ho fatto un po 'di ricerca e di ricerca, e ho preso alcuni spunti da FOSUserBundle.

Per rispondere alla mia prima domanda, sembra che nessuno dei due sia l'opzione migliore, rendendo così la seconda domanda discutibile.

Quello che ho finito per fare:

  • Aggiungi un nuovo field alla mia entity framework; Utente, $plainPassword . Ho quindi cambiato la mapping del mio UserType in questo field, invece di $ password direttamente.
    • Assicurati di cancellare $plainPassword in User::eraseCredentials
  • Creato un nuovo servizio chiamato UserManager. In questo, gli ho dato una function updateUser() che gestisce l'effettiva codifica della password (non più Controller gestito, yay!).

Questo è più o less ciò che fa FOSUserBundle. Quindi chiamano manualmente UpdateUser (credo dal Controller). Tuttavia, voglio essere in grado di dimenticare questo passaggio per la maggior parte. Ecco where gli events di Doctrine sono entrati in gioco.

Ho aggiunto due listener di Doctrine Event (entrambi a UserManager): prePersist e preUpdate.

Entrambi in pratica controllano se si tratta di un object Utente, quindi chiamano updateUser() per aggiornare la password dell'utente. preUpdate whereva fare un ulteriore passo per impostare manualmente il nuovo valore.

Per assicurarsi che si inneschi, User::setPlainPassword() cancella la password e aggiorna il mio salt (questo è necessario perché plainPassword non è una properties; mappata, quindi basta cambiarlo non consentirà all'utente di triggersre preUpdate).

Un sacco di pezzi mobili, ma ora che l'ho installato, each volta che uso User::setPlainPassword() per cambiare la password in chiaro (indipendentemente da where), ora codificherà e salverà correttamente i valori effettivi della password. Woot!


 namespace My\Bundle\UserBundle\DependencyInjection; use Doctrine\ORM\Event\PreUpdateEventArgs; use Doctrine\ORM\Event\LifecycleEventArgs; use My\Bundle\UserBundle\Entity\User; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; class UserManager { protected $encoderFactory; public function __construct(EncoderFactoryInterface $encoderFactory) { $this->encoderFactory = $encoderFactory; } public function getEncoder(User $user) { return $this->encoderFactory->getEncoder($user); } public function updateUser(User $user) { $plainPassword = $user->getPlainPassword(); if (!empty($plainPassword)) { $encoder = $this->getEncoder($user); $user->setPassword($encoder->encodePassword($plainPassword, $user->getSalt())); $user->eraseCredentials(); } } public function preUpdate(PreUpdateEventArgs $event) { $user = $event->getEntity(); if (!($user instanceof \GamePlan\Bundle\UserBundle\Entity\User)) { return; } $this->updateUser($user); $event->setNewValue('password', $user->getPassword()); //die($event->getOldValue('password') . ' ' . $event->getNewValue('password') . ' ' . $event->hasChangedField('password') ? 'Y' : 'N'); } public function prePersist(LifecycleEventArgs $event) { $user = $event->getEntity(); if (!($user instanceof \GamePlan\Bundle\UserBundle\Entity\User)) { return; } $this->updateUser($user); } } 

 // In My\Bundle\UserBundle\Entity\User public function setPlainPassword($plainPassword) { $this->plainPassword = $plainPassword; // Change some mapped values so preUpdate will get called. $this->refreshSalt(); // generates a new salt and sets it $this->password = ''; // just blank it out } 

 # In My/Bundle/UserBundle/Resources/config/services.yml services: my_user.manager: class: My\Bundle\UserBundle\DependencyInjection\UserManager arguments: - @security.encoder_factory tags: - { name: doctrine.event_listener, event: prePersist } - { name: doctrine.event_listener, event: preUpdate }