用于迁移遗留密码的自定义 Symfony FOSUserBundle 服务
Custom Symfony FOSUserBundle service for migrating legacy passwords
我正在尝试将我自己的旧密码服务插入到 Symfony3 中,以被动地从旧数据库迁移用户 table。
遗留系统的密码散列具有相同的硬编码 $salt
变量,用于所有成员(因此我的 FOSUserBundle table 目前所有要迁移的成员的 salt 列都是空的).
旧方法使用:
sha1($salt1.$password.$salt2)
新方法是 Symfony 的 FOSUserBundle 标准 bcrypt hash。
我正在尝试实现它,以便当旧用户首次登录时,Symfony 将尝试:
- 使用 FOSUserBundle 的标准 bcrypt 方法登录。
- 如果#1 没有成功,则尝试旧算法。
- 如果#2 成功,数据库中的密码散列和 salt table 将更新以符合标准 FOSUserBundle 方法
我一直在阅读有关如何插入服务以使其正常工作的信息,我认为我所掌握的以下内容在理论上似乎是正确的 - 如果没有的话 corrections/guidance 将不胜感激,因为我'无法测试!
但是,我不确定我应该如何将它全部连接到 Symfony 以便正常的 FOSUserBundle 进程将在步骤 1 失败时执行步骤 2 和 3
services.yml:
parameters:
custom-password-encoder:
class: AppBundle\Security\LegacyPasswordEncoder
security.yml:
security:
encoders:
#FOS\UserBundle\Model\UserInterface: bcrypt Commented out to try the following alternative to give password migrating log in
FOS\UserBundle\Model\UserInterface: { id: custom-password-encoder }
BCryptPasswordEncoder(标准 FOSUserBundle):
class BCryptPasswordEncoder extends BasePasswordEncoder
{
/* .... */
/**
* {@inheritdoc}
*/
public function encodePassword($raw, $salt)
{
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
$options = array('cost' => $this->cost);
if ($salt) {
// Ignore $salt, the auto-generated one is always the best
}
return password_hash($raw, PASSWORD_BCRYPT, $options);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid($encoded, $raw, $salt)
{
return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded);
}
}
LegacyPasswordEncoder:
namespace AppBundle\Security;
use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class LegacyPasswordEncoder extends BasePasswordEncoder
{
/**
* {@inheritdoc}
*/
public function encodePassword($raw,$salt)
{
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
list($salt1,$salt2) = explode(",",$salt);
return sha1($salt1.$raw.$salt2);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid($encoded, $raw, $salt)
{
list($salt1,$salt2) = explode(",",$salt);
return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded,sha1($salt1.$raw.$salt2));
}
}
首先将您的用户 class 映射到所需的编码器:
security:
hide_user_not_found: false
encoders:
Cerad\Bundle\UserBundle\Entity\User: # Replace with your user class
id: cerad_user.user_encoder # Replace with the service id for your encoder
这应该足以让您的编码器插入。
然后您需要通过扩展 BCryptPasswordEncoder 并覆盖 isPasswordValid 方法来实际编写您的自定义编码器。当然还要为它创建服务。很多东西要学。
如何调用 BcryptPasswordEncorder 和 LegacyPasswordEncoder?你不知道。至少不是直接的。 Symfony 没有密码链编码器。相反,编写自己的编码器并自己实现链接。
class MyEncoder extends BCryptPasswordEncoder
{
function isPasswordValid($encoded,$raw,$salt)
{
// Check the bcrypt
if (parent::isPasswordValid($encoded,$raw,$salt)) return true;
// Copied from legacy
list($salt1,$salt2) = explode(",",$salt);
return
!$this->isPasswordTooLong($raw) &&
$this>comparePasswords($encoded,sha1($salt1.$raw.$salt2));
并确保您在服务而非参数下定义编码器。还要确保将成本(默认值为 13)作为构造函数参数传递。
您的问题的解决方案是使用允许根据用户动态更改密码哈希算法的 Symfony 功能:https://symfony.com/doc/current/cookbook/security/named_encoders.html
这样,您可以将任何未迁移的用户标记为使用旧版算法。然后,在更新密码时,您将在保存用户之前重置正在使用的算法,以便使用新的更强大的算法对新密码进行哈希处理
我正在尝试将我自己的旧密码服务插入到 Symfony3 中,以被动地从旧数据库迁移用户 table。
遗留系统的密码散列具有相同的硬编码 $salt
变量,用于所有成员(因此我的 FOSUserBundle table 目前所有要迁移的成员的 salt 列都是空的).
旧方法使用:
sha1($salt1.$password.$salt2)
新方法是 Symfony 的 FOSUserBundle 标准 bcrypt hash。
我正在尝试实现它,以便当旧用户首次登录时,Symfony 将尝试:
- 使用 FOSUserBundle 的标准 bcrypt 方法登录。
- 如果#1 没有成功,则尝试旧算法。
- 如果#2 成功,数据库中的密码散列和 salt table 将更新以符合标准 FOSUserBundle 方法
我一直在阅读有关如何插入服务以使其正常工作的信息,我认为我所掌握的以下内容在理论上似乎是正确的 - 如果没有的话 corrections/guidance 将不胜感激,因为我'无法测试!
但是,我不确定我应该如何将它全部连接到 Symfony 以便正常的 FOSUserBundle 进程将在步骤 1 失败时执行步骤 2 和 3
services.yml:
parameters:
custom-password-encoder:
class: AppBundle\Security\LegacyPasswordEncoder
security.yml:
security:
encoders:
#FOS\UserBundle\Model\UserInterface: bcrypt Commented out to try the following alternative to give password migrating log in
FOS\UserBundle\Model\UserInterface: { id: custom-password-encoder }
BCryptPasswordEncoder(标准 FOSUserBundle):
class BCryptPasswordEncoder extends BasePasswordEncoder
{
/* .... */
/**
* {@inheritdoc}
*/
public function encodePassword($raw, $salt)
{
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
$options = array('cost' => $this->cost);
if ($salt) {
// Ignore $salt, the auto-generated one is always the best
}
return password_hash($raw, PASSWORD_BCRYPT, $options);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid($encoded, $raw, $salt)
{
return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded);
}
}
LegacyPasswordEncoder:
namespace AppBundle\Security;
use Symfony\Component\Security\Core\Encoder\BasePasswordEncoder;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class LegacyPasswordEncoder extends BasePasswordEncoder
{
/**
* {@inheritdoc}
*/
public function encodePassword($raw,$salt)
{
if ($this->isPasswordTooLong($raw)) {
throw new BadCredentialsException('Invalid password.');
}
list($salt1,$salt2) = explode(",",$salt);
return sha1($salt1.$raw.$salt2);
}
/**
* {@inheritdoc}
*/
public function isPasswordValid($encoded, $raw, $salt)
{
list($salt1,$salt2) = explode(",",$salt);
return !$this->isPasswordTooLong($raw) && $this->comparePasswords($encoded,sha1($salt1.$raw.$salt2));
}
}
首先将您的用户 class 映射到所需的编码器:
security:
hide_user_not_found: false
encoders:
Cerad\Bundle\UserBundle\Entity\User: # Replace with your user class
id: cerad_user.user_encoder # Replace with the service id for your encoder
这应该足以让您的编码器插入。
然后您需要通过扩展 BCryptPasswordEncoder 并覆盖 isPasswordValid 方法来实际编写您的自定义编码器。当然还要为它创建服务。很多东西要学。
如何调用 BcryptPasswordEncorder 和 LegacyPasswordEncoder?你不知道。至少不是直接的。 Symfony 没有密码链编码器。相反,编写自己的编码器并自己实现链接。
class MyEncoder extends BCryptPasswordEncoder
{
function isPasswordValid($encoded,$raw,$salt)
{
// Check the bcrypt
if (parent::isPasswordValid($encoded,$raw,$salt)) return true;
// Copied from legacy
list($salt1,$salt2) = explode(",",$salt);
return
!$this->isPasswordTooLong($raw) &&
$this>comparePasswords($encoded,sha1($salt1.$raw.$salt2));
并确保您在服务而非参数下定义编码器。还要确保将成本(默认值为 13)作为构造函数参数传递。
您的问题的解决方案是使用允许根据用户动态更改密码哈希算法的 Symfony 功能:https://symfony.com/doc/current/cookbook/security/named_encoders.html
这样,您可以将任何未迁移的用户标记为使用旧版算法。然后,在更新密码时,您将在保存用户之前重置正在使用的算法,以便使用新的更强大的算法对新密码进行哈希处理