5

这个关于 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

在 setter 模型内部:

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

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

4

2 回答 2

11

虽然我同意@Vadim 的观点,即您不应该将业务逻辑泄漏到您的模型中,但我会小心地将明文密码的散列推迟到prePersist事件发生,例如,除非persistflushsetPassword. 同时调用将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);
    }
    // ...
}

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

public function userRegistrationAction()
{
    // ... 
    if ($form->isValid()) {
        $user = new User();
        // ...
        $this->get('my.bundle.user_manager')->setUserPassword($user, $form->get('password')->getData());
        // ...
    }
}
于 2013-06-23T05:29:33.790 回答
3

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

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

FosUserBundle 用户管理器

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

于 2013-02-14T21:44:13.917 回答