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

时间:2013-02-14 20:43:51

标签: symfony models code-organization

关于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);

基础配置:

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

    encoders:
        Acme\UserBundle\Entity\User: sha512

在二传手模型中:

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

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

2 个答案:

答案 0 :(得分:11)

虽然我同意@Vadim您不应该将业务逻辑泄漏到您的模型中,但我会小心推迟明文密码的散列,直到prePersist事件,例如,除非您致电{在persist之后{1}}和flush。在此期间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);
    }
    // ...
}

答案 1 :(得分:3)

实体包含数据,而不是处理它。如果要更改实体的数据,可以创建事件侦听器并在持久性之前执行操作。从官方文档中查看How to Register Event Listeners and Subscribers

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

FosUserBundle UserManager

因此,主要思想是将普通密码从表单传递给用户实体,并在使用事件监听器进行persitence之前对其进行编码。