2011-02-08 57 views
2

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

我目前正在研究本网站的“版本2”,这次使用Symfony和Doctrine。新版本工作正常,我使用sfDoctrineGuard插件进行用户管理。

我想将现有用户迁移到新的应用程序中,尽量不要大惊小怪,保留现有的用户名和密码。我的主要问题是,我想改变我使用的密码哈希值。

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

所以 - 我的问题是,由于我可以用我自定义的plain-MD5密码散列算法成功迁移到sfDoctrineGuard用户群中,有什么办法可以转换这些用户,以便他们使用标准,腌制SHA1 sfDoctrineGuard算法?

我想我只能在每个用户登录时为每个用户执行此操作,因为这是我唯一拥有用户重新哈希密码的明文密码。我想我需要做的就是在“这个用户刚刚用这个密码成功登录”的时候挂钩了一些东西,这样我就可以将用户的算法,盐和密码设置到新的SHA1系统中,并将用户保存回数据库没有他们甚至知道它。

我挖了一下,我找不到一种方法来覆盖或挂钩到sfDoctrineGuard(特别是sfGuardSecurityUser,我认为?)登录系统在正确的位置。那么,不是没有黑客入侵实际的插件文件,这似乎是邪恶的。

任何Symfony/sfDoctrineGuard专家都指出我在正确的方向吗?

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

回答

1

您有足够的选项来解决您的问题。

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

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

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

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

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

+0

啊!这可能只是我需要的线索。我已经尝试在我的myUser类中实现自己的checkPassword版本,但它从来没有被调用(奇怪的是,它看起来像sfGuardSecurityUser的checkPassword()永远不会被调用,这使它成为一个红鲱鱼!)但进一步跟踪事情,它实际上是进行检查的PluginsfGuardUser,现在我知道在你提到的目录中有一个可覆盖的版本 - 我没有发现 - 我应该能够将我的代码放在那里。谢谢! – 2011-02-09 20:02:12

0

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

为了帮助其他任何想要做这种事的人,下面是我所做的。

首先,我将我现有的用户(使用从旧数据库转储的文本文件中的夹具加载)迁移到我的数据库中。我使用了一种自定义算法,在数据加载过程中将未加密的MD5密码保持不变(称为UniqueSentence :: unsaltednotransform)。这给了我sf_guard_user中的用户在'algorithm'中'password'和'UniqueSentence :: unsaltednotransform'中的旧密码散列值。 (你可以直接将行迁移到表中,我只是觉得把它作为灯具很方便。)

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

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()。

这似乎工作成功 - 如果我作为一个迁移的用户登录,它就像普通用户一样工作,但如果我以后检查数据库,他们的算法,salt和哈希密码已按预期更新。

相关问题