我有一个现有的,基于非框架的PHP / MySQL网站。它有一个简单的安全模型,带有用户名和散列(MD5)密码的用户表。
我目前正致力于本网站的“第2版”,这次是使用Symfony和Doctrine。新版本运行正常,我正在使用sfDoctrineGuard插件进行用户管理。
我希望将现有用户迁移到新应用中,而不用大惊小怪,保留现有的用户名和密码。不过,我的主要问题是我想更改我正在使用的密码哈希。
当前站点使用密码 * 的未经删除的MD5哈希值。我已经想出了如何在保持现有算法的同时将用户迁移到Symfony / sfDoctrineGuard(通过为未加盐的MD5提供我自己的“算法”功能。)但是,未加盐的md5显然不是理想的。
所以 - 我的问题是,鉴于一大堆用户可以使用我的自定义普通MD5密码哈希算法成功迁移到sfDoctrineGuard用户,我有什么方法可以转换这些用户,以便他们使用标准,盐渍SHA1 sfDoctrineGuard算法?
我认为我只能在每个用户登录时为每个用户执行此操作,因为这是我唯一一次使用用户的明文密码进行重新散列。我想我需要做的是在“这个用户刚刚使用此密码成功登录”的点上挂钩,这样我就可以将用户的算法,盐和密码设置为新的SHA1系统,并将用户保存回没有他们的数据库甚至不知道它。
我已经挖了一下,我无法找到一种方法来覆盖或挂钩sfDoctrineGuard(特别是sfGuardSecurityUser,我认为?)登录系统在正确的位置。好吧,不是没有乱砍实际的插件文件,这似乎是邪恶的。
Symfony / sfDoctrineGuard专家可以指出我的方向正确吗?
*不要那样看着我,这是我的第一个网站!至少我没有将它们存储在明文中......
答案 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()。
这似乎成功运行 - 如果我以迁移用户身份登录,它就像普通用户一样工作,但如果我之后检查数据库,他们的算法,盐和散列密码已按预期更新。