2013-02-14 18 views
5

Questa domanda Symfony 2.1Come utilizzare la codifica di fabbrica in Symfony 2 all'interno del modellatore?

Come posso codificare la password dell'utente con:

$factory = $this->get('security.encoder_factory'); 
$user = new Acme\UserBundle\Entity\User(); 

$encoder = $factory->getEncoder($user); 
$password = $encoder->encodePassword('ryanpass', $user->getSalt()); 
$user->setPassword($password); 

e base config:

# app/config/security.yml 
security: 
    # ... 

    encoders: 
     Acme\UserBundle\Entity\User: sha512 

All'interno dei modelli setter:

class User implements UserInterface, \Serializable 
{ 
    public function setPassword($password) 
    { 
     $this->password = $password; 
    } 
} 

I ritengo che il processo di crittografia della password debba essere gestito da mo del. Come posso utilizzare la fabbrica di encoder standard all'interno del modello?

risposta

3

L'entità contiene dati, non la gestisce. Se vuoi cambiare i dati di un'entità, puoi creare il listener di eventi e fare cose prima della persistenza. Controllare How to Register Event Listeners and Subscribers dalla documentazione ufficiale.

Puoi anche dare un'occhiata a FosUserBundle e alla sua gestione degli utenti.

FosUserBundle UserManager

Così, l'idea principale è quella di passare una password semplice da un modulo per l'entità utente e codificarlo prima di persitence utilizzando listener di eventi.

+0

Sì, le entità possono gestire anche i dati. Ad esempio è possibile aggiungere un RUOLO a un utente che non ha nessuno nel metodo getter come spiegato qui: https://knpuniversity.com/screencast/symfony-security/dynamic-roles Non metterei tutto nell'entità ma si sta impostando password, e questo è ciò che fa la funzione, quindi ha senso secondo me. –

10

Mentre sono d'accordo con @Vadim che non si deve perdere la logica di business nel modello, vorrei stare attenti con rinviando la hashing della password in chiaro fino a quando l'evento prePersist, per esempio, a meno che non si chiama persist e flush destra dopo setPassword. Una chiamata getPassword restituirà la stringa di testo in chiaro a meno che non sia stata memorizzata in un campo separato, il che potrebbe avere conseguenze gravi. Idealmente, la password in chiaro dovrebbe esistere per il minor tempo possibile all'interno del ciclo di vita dell'applicazione.

mi consiglia di utilizzare un livello di servizio in cui un "User Manager" fornisce un'interfaccia per le operazioni più comuni, in modo che non c'è bisogno di inquinare la vostra proprietà password anche temporaneamente:

class UserManager 
{ 
    // ... 
    public function __construct(EncoderFactoryInterface $encoderFactory) 
    { 
     // $encoderFactory is injected by the DIC as requested by your service configuration 
     // ... 
    } 

    public function setUserPassword(UserInterface $user, $plaintextPassword) 
    { 
     $hash = $this->encoderFactory->getEncoder($user)->encodePassword($plaintextPassword, null); 
     $user->setPassword($hash); 
    } 
    // ... 
} 

nel controller per la registrazione modulo di invio, ad esempio:

public function userRegistrationAction() 
{ 
    // ... 
    if ($form->isValid()) { 
     $user = new User(); 
     // ... 
     $this->get('my.bundle.user_manager')->setUserPassword($user, $form->get('password')->getData()); 
     // ... 
    } 
}