如何在模型设定器内使用Symfony 2中的编码器工厂?

Yur*_*ury 5 code-organization models symfony

关于Symfony 2.1的这个问题

如何编码用户密码:

$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);
Run Code Online (Sandbox Code Playgroud)

和基础配置:

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

    encoders:
        Acme\UserBundle\Entity\User: sha512
Run Code Online (Sandbox Code Playgroud)

在setter模型中:

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

我认为加密密码的过程必须按模型处理.如何在模型中使用标准编码器工厂?

Adr*_*ter 11

虽然我同意@Vadim你不应该将业务逻辑泄漏到你的模型中,但我会小心推迟明文密码的散列直到prePersist事件,例如,除非你打电话persistflush之后setPassword.一个getPassword在此期间调用将返回该明文字符串,除非你已经将其存储在一个单独的领域,这可能造成严重后果.理想情况下,明文密码应在应用程序生命周期内尽可能短的时间内存在.

我建议使用服务层,其中"用户管理器"提供常见任务的接口,这样您即使是临时也不需要污染密码属性:

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);
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在您的控制器中提交注册表单,例如:

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


Vad*_*man 3

实体包含数据,但不处理数据。如果您想更改实体的数据,您可以创建事件侦听器并在持久化之前执行一些操作。查看官方文档如何注册事件监听器和订阅者。

您还可以查看FosUserBundle及其用户管理。

FosUserBundle 用户管理器

因此,主要思想是将纯密码从表单传递到用户实体,并在使用事件侦听器持久化之前对其进行编码。