2012-04-01 21 views
9

Tôi đang cố gắng để đặt cùng một tính năng thay đổi mật khẩu trong Symfony2. Tôi có trường "mật khẩu hiện tại", trường "mật khẩu mới" và trường "xác nhận mật khẩu mới" và phần tôi hiện đang tập trung vào đang xác thực trường "mật khẩu hiện tại".Members một mật khẩu trong Symfony2

(Bằng cách này, tôi nhận ra rằng những thứ như FOSUserBundle tồn tại sẽ chăm sóc rất nhiều thứ cho tôi, nhưng tôi đã xây dựng hệ thống xác thực dựa trên tài liệu chính thức của Symfony và tôi không có thời gian ngay bây giờ để làm lại tất cả các mã xác thực của tôi)

Những gì tôi đang tưởng tượng/hy vọng tôi có thể làm là tạo một callback xác nhận nói rằng một cái gì đó như thế này:.

// 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); 
    } 
} 

như bạn thấy trong ý kiến ​​của tôi , có ít nhất một vài lý do khiến mã trên không hoạt động. Tôi sẽ chỉ đăng những câu hỏi cụ thể về những vấn đề cụ thể đó, nhưng có lẽ tôi đang sủa cây sai hoàn toàn. Đó là lý do tại sao tôi hỏi câu hỏi tổng thể.

Vì vậy, làm thế nào tôi có thể xác nhận mật khẩu của người dùng?

Trả lời

10

Có một built-in constraint cho rằng kể từ khi Symfony 2.1.


Trước tiên, bạn nên tạo custom validation constraint. Bạn có thể đăng ký validator như một dịch vụ và tiêm bất cứ thứ gì bạn cần vào nó.

Thứ hai, vì bạn có thể không muốn thêm trường cho mật khẩu hiện tại vào lớp Người dùng chỉ để gắn ràng buộc vào nó, bạn có thể sử dụng tên gọi là form model. Về cơ bản, bạn tạo một lớp trong không gian tên Form\Model giữ trường mật khẩu hiện tại và tham chiếu đến đối tượng người dùng. Bạn có thể gắn ràng buộc tùy chỉnh của bạn vào trường mật khẩu đó rồi. Sau đó, bạn tạo loại biểu mẫu thay đổi mật khẩu của mình dựa trên mẫu biểu mẫu này.

Dưới đây là một ví dụ về một hạn chế từ một trong những dự án của tôi:

<?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'; 
    } 
} 

Và validator của nó:

<?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; 
    } 
} 

tôi sử dụng Blofwish password encoder bundle của tôi, vì vậy tôi không vượt qua muối như là đối số thứ ba với phương pháp $encoder->isPasswordValid(), nhưng tôi nghĩ bạn sẽ có thể tự điều chỉnh ví dụ này theo nhu cầu của mình.

Ngoài ra, tôi đang sử dụng JMSDiExtraBundle để đơn giản hóa phát triển, nhưng bạn có thể sử dụng tất nhiên cấu hình chứa phục vụ cách cổ điển.

+0

Được rồi, cảm ơn. Nhưng phần xác thực mật khẩu thực sự thì sao? Đó là câu hỏi của tôi. Tôi đã biết cách tạo trình xác nhận tùy chỉnh và cách tạo các trường biểu mẫu. –

+0

Đã thêm ví dụ. –

+0

Tuyệt vời, cảm ơn. Tôi sẽ thử. –

0

FOSUserBundle sử dụng lớp ModelManager tách rời khỏi cơ sở Model. Bạn có thể kiểm tra implementation của họ.

-3

tôi đã kết thúc cắt nút thắt Gordian. Tôi bỏ qua tất cả các công cụ biểu mẫu của Symfony và đã làm tất cả các logic trong bộ điều khiển.

+1

Xin chào, bạn nên thử lại với ràng buộc xác thực UserPassword mới. – Acyra

6

Trong Symfony 2.1 bạn có thể sử dụng được xây dựng trong validator: http://symfony.com/doc/master/reference/constraints/UserPassword.html

Vì vậy, ví dụ trong xây dựng hình của bạn:

// 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())) 

Rõ ràng có một lỗi ngay bây giờ với validator rằng như vậy có thể hay bây giờ có thể làm việc https://github.com/symfony/symfony/issues/5460

+1

một lưu ý nhỏ, có lỗi đánh máy, phải là 'Symfony \ Component \ Security \ Core \ Validator \ Constraints \ UserPassword' (' s' bị thiếu trong Contraints) – loostro

Các vấn đề liên quan