2

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

我目前正在开发这个网站的“版本 2”,这次使用 Symfony 和 Doctrine。新版本运行良好,我正在使用 sfDoctrineGuard 插件进行用户管理。

我想以最少的麻烦将现有用户迁移到新应用程序中,保留他们现有的用户名和密码。不过,我的主要问题是我想更改我正在使用的密码哈希。

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

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

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

我已经挖了一点,我想不出一种方法来覆盖或挂钩到 sfDoctrineGuard(特别是 sfGuardSecurityUser,我想?)登录系统在正确的位置。好吧,并非没有破解实际的插件文件,这看起来很邪恶。

那里有任何 Symfony/sfDoctrineGuard 专家可以指出我正确的方向吗?

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

4

2 回答 2

1

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

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

如果您需要更改 sfGuardSecurityUser 中的某些内容,则可以在应用程序的 User 类(实际上扩展 sfGuardSecurityUser)中进行。

也可以重载默认放入 lib/model/doctrine/sfDoctrineGuardPlugin 目录的模型类。

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

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

于 2011-02-09T17:55:51.443 回答
0

感谢 kuba,他为我指明了正确的方向。

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

首先,我将现有用户(使用从旧数据库转储的文本文件中的固定负载)迁移到我的数据库中。我使用了一种自定义算法,该算法在数据加载期间保持未加盐的 MD5 密码不变(称为 UniqueSentence::unsaltednotransform)。这给了我 sf_guard_user 中的用户,在“算法”中的“密码”和“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,并重新设置密码(首先将盐设置为空,因此它也会重新生成。)然后它只是直接使用基类中的标准 checkPassword() 。

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

于 2011-02-09T20:36:07.397 回答