2012-04-01 6 views
9

Ich versuche, ein Änderungskennwort in Symfony2 zusammenzustellen. Ich habe ein "aktuelles Passwort" -Feld, ein "neues Passwort" -Feld und ein "Bestätige neues Passwort" -Feld, und der Teil, auf den ich mich gerade konzentriere, überprüft das Feld "aktuelles Passwort".Überprüfen eines Passworts in Symfony2

(Übrigens, ich realisiere jetzt, dass Dinge wie FOSUserBundle existieren, dass würde eine Menge dieser Dinge für mich kümmern, aber ich baute bereits mein Authentifizierungssystem basierend auf der offiziellen Symfony-Dokumentation, und ich habe nicht Zeit jetzt alle meine Authentifizierungscode zu wiederholen)

Was ich mir vor/gehofft, ich tun kann, ist eine Validierung Rückruf erstellen, die so etwas wie dies sagt.

// Entity/User.php 

public function currentPasswordIsValid(ExecutionContext $context) 
{ 
    $currentPassword = $whatever; // whatever the user submitted as their current password 
    $factory = $this->get('security.encoder_factory'); // Getting the factory this way doesn't work in this context. 
    $encoder = $factory->getEncoder($this); 
    $encryptedCurrentPassword = $encoder->encodePassword($this->getPassword(), $this->getSalt()); 

    if ($encyptedCurrentPassword != $this->getPassword() { 
    $context->addViolation('Current password is not valid', array(), null); 
    } 
} 

wie Sie meine Kommentare sehen , es gibt mindestens ein paar Gründe, warum der obige Code nicht funktioniert. Ich würde nur bestimmte Fragen zu diesen speziellen Themen stellen, aber vielleicht belle ich den falschen Baum überhaupt an. Deshalb stelle ich die Gesamtfrage.

Wie kann ich das Passwort eines Benutzers bestätigen?

Antwort

10

Seit Symfony 2.1 gibt es eine built-in constraint.


Zuerst sollten Sie eine custom validation constraint erstellen. Sie können den Validator als Dienst registrieren und alles injizieren, was Sie benötigen.

Zweitens, da Sie wahrscheinlich nicht ein Feld für das aktuelle Passwort der Benutzerklasse hinzufügen möchten, nur um die Einschränkung zu halten, könnten Sie verwenden, was eine form model heißt. Im Wesentlichen erstellen Sie eine Klasse im Namespace Form\Model, die das aktuelle Kennwortfeld und einen Verweis auf das Benutzerobjekt enthält. Sie können dann Ihre benutzerdefinierte Einschränkung an dieses Passwortfeld anheften. Dann erstellen Sie Ihren Kennwortänderungstyp für dieses Formularmodell.

Hier ist ein Beispiel für eine Einschränkung von einem meiner Projekte:

<?php 
namespace Vendor\Bundle\AppBundle\Validator\Constraints\User; 

use Symfony\Component\Validator\Constraint; 

/** 
* @Annotation 
*/ 
class CurrentPassword extends Constraint 
{ 
    public $message = "Your current password is not valid"; 

    /** 
    * @return string 
    */ 
    public function validatedBy() 
    { 
     return 'user.validator.current_password'; 
    } 
} 

Und seine Validator:

<?php 
namespace Vendor\Bundle\AppBundle\Validator\Constraints\User; 

use Symfony\Component\Validator\ConstraintValidator; 
use Symfony\Component\Validator\Constraint; 
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; 
use Symfony\Component\Security\Core\SecurityContextInterface; 
use JMS\DiExtraBundle\Annotation\Validator; 
use JMS\DiExtraBundle\Annotation\InjectParams; 
use JMS\DiExtraBundle\Annotation\Inject; 

/** 
* @Validator("user.validator.current_password") 
*/ 
class CurrentPasswordValidator extends ConstraintValidator 
{ 
    /** 
    * @var EncoderFactoryInterface 
    */ 
    private $encoderFactory; 

    /** 
    * @var SecurityContextInterface 
    */ 
    private $securityContext; 

    /** 
    * @InjectParams({ 
    *  "encoderFactory" = @Inject("security.encoder_factory"), 
    *  "securityContext" = @Inject("security.context") 
    * }) 
    * 
    * @param EncoderFactoryInterface $encoderFactory 
    * @param SecurityContextInterface $securityContext 
    */ 
    public function __construct(EncoderFactoryInterface $encoderFactory, 
           SecurityContextInterface $securityContext) 
    { 
     $this->encoderFactory = $encoderFactory; 
     $this->securityContext = $securityContext; 
    } 

    /** 
    * @param string  $currentPassword 
    * @param Constraint $constraint 
    * @return boolean 
    */ 
    public function isValid($currentPassword, Constraint $constraint) 
    { 
     $currentUser = $this->securityContext->getToken()->getUser(); 
     $encoder = $this->encoderFactory->getEncoder($currentUser); 
     $isValid = $encoder->isPasswordValid(
      $currentUser->getPassword(), $currentPassword, null 
     ); 

     if (!$isValid) { 
      $this->setMessage($constraint->message); 
      return false; 
     } 

     return true; 
    } 
} 

ich meine Blofwish password encoder bundle, so dass ich nicht passieren Salz als drittes Argument zu der $encoder->isPasswordValid() Methode, aber ich denke, dass Sie in der Lage sein werden, dieses Beispiel an Ihre Bedürfnisse selbst anzupassen.

Auch verwende ich JMSDiExtraBundle, um die Entwicklung zu vereinfachen, aber Sie können natürlich die klassische Service-Container-Konfiguration verwenden.

+0

Okay, danke. Aber was ist mit dem eigentlichen Passwort-Validierungsteil? Das war meine Frage. Ich weiß bereits, wie man einen benutzerdefinierten Validator erstellt und wie man Formularfelder erstellt. –

+0

Ein Beispiel hinzugefügt. –

+0

Super, danke. Ich werde es versuchen. –

0

FOSUserBundle verwendet eine ModelManager Klasse, die von der Basis Model getrennt ist. Sie können ihre implementation überprüfen.

-3

Ich endete den Gordischen Knoten schneiden. Ich habe alle Symfony-Formulare umgangen und die gesamte Logik im Controller ausgeführt.

+1

Hey, Sie sollten es erneut mit der neuen UserPassword Validierung Constraint versuchen. – Acyra

6

In Symfony 2.1 können Sie die Einbau-Validator verwenden: http://symfony.com/doc/master/reference/constraints/UserPassword.html

So zum Beispiel in der Form Builder:

// declare 
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; 

// mapped=>false (new in 2.1) is to let the builder know this is not an entity field 
->add('currentpassword', 'password', array('label'=>'Current password', 'mapped' => false, 'constraints' => new UserPassword())) 

Anscheinend gibt es einen Fehler im Augenblick mit dem Validator so könnte oder jetzt arbeiten https://github.com/symfony/symfony/issues/5460

+1

eine kleine Notiz, es gibt einen Tippfehler, sollte es Symfony \ Component \ Security \ Core \ Validator \ Constraints \ UserPassword sein (das 's' fehlt in Contraints) – loostro

Verwandte Themen