2012-04-01 2 views
9

Symfony2에 비밀번호 변경 기능을 추가하려고합니다. "현재 암호"필드, "새 암호"필드 및 "새 암호 확인"필드가 있으며 현재 초점을 맞추고있는 부분은 "현재 암호"필드의 유효성 검사입니다.Symfony2에서 비밀번호 확인

(덧붙여서,과 같은 것이 존재한다는 것을 알았지 만, 이미 공식적인 Symfony 문서를 기반으로하는 인증 시스템을 구축했으며, 지금 시간 내 모든 인증 코드를 다시 실행)

은 내가 내가 할 수있는 희망/상상하고있어 말한다 유효성 검사 콜백을 만드는 것입니다 이런 식으로 뭔가 :. 당신이 내 의견에서 볼 수 있듯이

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

, 위의 코드가 작동하지 않는 몇 가지 이유가 있습니다. 나는 그 특정 쟁점들에 대한 구체적인 질문들을 게시 할 것이지만, 아마도 나는 잘못된 나무를 완전히 짖고있을 것입니다. 그래서 제가 전반적인 질문을하고 있습니다.

그럼 어떻게 사용자의 비밀번호를 확인할 수 있습니까?

답변

10

Symfony 2.1 이후로 built-in constraint이 있습니다.


먼저 custom validation constraint을 만들어야합니다. 검사기를 서비스로 등록하고 필요한 것을 주입 할 수 있습니다.

두 번째로, 제약 조건을 적용하기 위해 현재 패스워드 필드를 User 클래스에 추가하지 않으려는 경우 form model을 사용할 수 있습니다. 기본적으로 현재 암호 필드와 사용자 개체에 대한 참조를 보유하는 클래스를 Form\Model 네임 스페이스에 만듭니다. 그러면 사용자 정의 제약 조건을 해당 암호 필드에 적용 할 수 있습니다. 그런 다음이 양식 모델에 대해 암호 변경 양식 유형을 작성합니다.

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

그리고 그 검증 : 여기

내 프로젝트 중 하나 제약의 예

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

내가 내 Blofwish password encoder bundle를 사용, 그래서 세 번째 인수로 소금을 통과하지 $encoder->isPasswordValid() 방법을 사용하는 것이지만,이 예를 자신의 필요에 맞게 직접 적용 할 수있을 것이라고 생각합니다.

또한 개발을 단순화하기 위해 JMSDiExtraBundle을 사용하고 있지만 물론 고전적인 서비스 컨테이너 구성 방법을 사용할 수 있습니다.

+0

알겠습니다. 고마워요. 그러나 실제 암호 유효성 검사 부분은 어떻습니까? 그게 내 질문에 묻고있는거야. 저는 이미 사용자 정의 유효성 검사기를 만드는 방법과 양식 필드를 만드는 방법을 알고 있습니다. –

+0

예제를 추가했습니다. –

+0

신난다. 고마워. 나는 그것을 시도 할 것이다. –

0

FOSUserBundle은 과는 별도로 클래스를 사용합니다. implementation을 확인할 수 있습니다.

-3

나는 고르 디아 매듭을 자르려고했다. Symfony의 모든 폼을 우회하여 컨트롤러의 모든 로직을 수행했습니다.

+1

새 UserPassword 유효성 확인 제약 조건으로 다시 시도해야합니다. – Acyra

6

Symfony 2에서.양식 빌더에서 예를 들면 그래서 http://symfony.com/doc/master/reference/constraints/UserPassword.html

: 1 당신은 내장 된 검증을 사용할 수 있도록하거나 지금 작동 할 수있는 그 검증과 지금

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

은 분명히 버그있다 https://github.com/symfony/symfony/issues/5460

+1

작은 메모, 오타가 있습니다,'Symfony \ Component \ Security \ Core \ Validator \ Constraints \ UserPassword'이어야합니다 (Contraints에는's'가 없습니다) – loostro

관련 문제