将现有用户和密码迁移到新的Symfony / sfDoctrineGuard用户系统

时间:2011-02-08 16:06:35

标签: security symfony1 passwords doctrine sfdoctrineguard

我有一个现有的,基于非框架的PHP / MySQL网站。它有一个简单的安全模型,带有用户名和散列(MD5)密码的用户表。

我目前正致力于本网站的“第2版”,这次是使用Symfony和Doctrine。新版本运行正常,我正在使用sfDoctrineGuard插件进行用户管理。

我希望将现有用户迁移到新应用中,而不用大惊小怪,保留现有的用户名和密码。不过,我的主要问题是我想更改我正在使用的密码哈希。

当前站点使用密码 * 的未经删除的MD5哈希值。我已经想出了如何在保持现有算法的同时将用户迁移到Symfony / sfDoctrineGuard(通过为未加盐的MD5提供我自己的“算法”功能。)但是,未加盐的md5显然不是理想的。

所以 - 我的问题是,鉴于一大堆用户可以使用我的自定义普通MD5密码哈希算法成功迁移到sfDoctrineGuard用户,我有什么方法可以转换这些用户,以便他们使用标准,盐渍SHA1 sfDoctrineGuard算法?

我认为我只能在每个用户登录时为每个用户执行此操作,因为这是我唯一一次使用用户的明文密码进行重新散列。我想我需要做的是在“这个用户刚刚使用此密码成功登录”的点上挂钩,这样我就可以将用户的算法,盐和密码设置为新的SHA1系统,并将用户保存回没有他们的数据库甚至不知道它。

我已经挖了一下,我无法找到一种方法来覆盖或挂钩sfDoctrineGuard(特别是sfGuardSecurityUser,我认为?)登录系统在正确的位置。好吧,不是没有乱砍实际的插件文件,这似乎是邪恶的。

Symfony / sfDoctrineGuard专家可以指出我的方向正确吗?

*不要那样看着我,这是我的第一个网站!至少我没有将它们存储在明文中......

2 个答案:

答案 0 :(得分:1)

您有很多选择来解决您的问题。

您可以在sfDoctrineGuardPlugin中重载或更改几乎所有内容。

如果您需要在sfGuardSecurityUser中更改某些内容,而不是在应用程序的User类(实际上扩展sfGuardSecurityUser)中执行此操作。

也可以重载模型类,默认情况下将这些类放入lib / model / doctrine / sfDoctrineGuardPlugin目录。

您也可以扩展默认保护架构。例如,您可以添加一个字段,告诉您用户是否更改了密码,如果他没有,则更新密码。

最后,您可以实现自定义密码检查和设置算法: http://www.symfony-project.org/plugins/sfDoctrineGuardPlugin?tab=plugin_readme(滚动到“使用外部方法检查用户密码”和“更改用于存储密码的算法”)。

答案 1 :(得分:0)

感谢库巴,他指出了我正确的方向。

为了帮助那些想要做这样事情的人,这就是我所做的。

首先,我将现有用户(使用从旧数据库转储的文本文件中的夹具加载)迁移到我的数据库中。我使用了一种自定义算法,在数据加载期间保持我的无盐MD5密码不变(称为UniqueSentence :: unsaltednotransform)。这使我在sf_guard_user中的用户在'password'中使用旧密码哈希,在'algorithm'中使用'UniqueSentence :: unsaltednotransform'。 (你也可以直接将行迁移到表中,我觉得将我的作为固定装置很方便。)

然后我在/lib/model/doctrine/sfDoctrineGuardPlugin/sfGuardUser.class.php中添加了我自己的自定义checkPassword函数,如下所示:

class sfGuardUser extends PluginsfGuardUser
{
  public function checkPassword($password)
  {
    if ($this->getAlgorithm() == 'UniqueSentence::unsaltednotransform') {
      // Our password has been set by a fixture load that left it in its
      // original state from the old system, an unsalted MD5.

      // Has the user got the right password?
      if (md5($password) != $this->getPassword()) {
        return false;
      }
      // Yes. So, now we re-set the password.
      $this->setSalt(''); // An empty salt will be regenerated
      // Use a smarter algorithm
      $algorithm = sfConfig::get('app_sf_guard_plugin_algorithm_callable', 'sha1');
      $this->setAlgorithm($algorithm); 
      $this->setPassword($password);
      // Could just return true here, but dropping through to the usual
      // method means that if we've broken something, we'll know sooner 
      // rather than later.
    }
    // Just pass the call onto the usual method.
    return parent::checkPasswordByGuard($password);
  }
}

如您所见,它非常简单 - 如果它检测到具有旧密码算法的用户,则使用旧算法验证密码,然后,如果它是正确的密码,则将算法更改为SHA1,并且重新设置密码(首先将salt设置为空,以便重新生成。)然后它将直接使用基类中的标准checkPassword()。

这似乎成功运行 - 如果我以迁移用户身份登录,它就像普通用户一样工作,但如果我之后检查数据库,他们的算法,盐和散列密码已按预期更新。