我正在阅读Cake 3网站here上的Auth文档,我仍然对如何将用户密码迁移到新应用程序感到困惑。
它说要包含FallbackPasswordHasher类,但如果是这样的话,我在哪里放置旧密码的盐(因为新网站不同)?除此之外,一切似乎都是不言自明的。
我有一些不同但相关的网站我正在整合到一个网站中,该网站将在多个企业中提供相同的服务,因此我需要从具有不同盐的各种网站导入用户密码。
答案 0 :(得分:6)
根据所使用的机制和算法,您可能不需要旧的盐,因为它已经附加到哈希,例如,使用Blowfish
密码进行哈希处理的密码就是这种情况hasher,或者通常使用crypt()
进行哈希密码,可以通过Default
密码哈希来验证它们。
因此,如果所有密码都属于这种情况,那么您根本不需要使用Fallback
密码哈希,而只需使用Default
密码哈希,并在必要时重新密码密码as shown in the docs。
对于使用不将哈希值附加到哈希值的机制进行密码散列,例如md5()
,sha1()
,mhash()
等,您可能需要自定义旧密码哈希它包含了用于旧密码的盐。
在大多数情况下,WeakPassword
hasher应该完成这项工作,它使用旧的Cake 2机制和salt配置,即全局Security.salt
选项和hashType
hasher选项。 / p>
参见 Cookbook > Authentication > Changing Hashing Algorithms
如果您的旧版应用程序中使用了自定义哈希,那么弱的哈希对您不起作用,那么您将需要一个自定义的遗留哈希。遗留密码hasher can be found in the docs的示例,包含salt应该像例如
一样简单namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher {
public function hash($password) {
throw new \LogicException('You really should not use me!');
}
public function check($password, $hashedPassword) {
// compare using the legacy salt
return sha1($password . 'legacy-salt-here') === $hashedPassword;
}
}
请注意,在使用Fallback
哈希的情况下,传统的哈希不需要实现hash()
来实际哈希,因为您不应该将其用于新哈希。< / p>
使用来自使用单个盐的不同来源的密码可能会使事情变得更复杂。
有多种方法可以解决这个问题,最明显的一种方法(因为这是Fallback
hasher的工作方式)将为每个应用创建一个单独的自定义传统哈希,其中不同的哈希将使用适当的盐,也可能使用特定应用程序的算法。
您需要做的就是依靠Fallback
哈希迭代所有旧版哈希,直到其中一个成功验证密码。
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => ['Default', 'LegacyApp1', 'LegacyApp2', 'LegacyApp3', /* ... */]
]
基本上,是的,这里唯一的问题可能是冲突,即 App X 的哈希会成功验证密码,该密码通常被哈希的<{1}}评估为< strong> App Y 密码源自。
如果这种情况可能出于某种原因(即使对于那么弱的MD5而言通常也不太可能),您必须寻求更严格的解决方案。
可能有10 ^ Cake方法可以解决这样的问题,所以由于碰撞应该不太可能,我会坚持认为最基本的方法,那就是在合并之前修改密码他们添加了一个标识旧应用程序的标识符,然后旧密码可以使用它来选择适当的salt和算法。
例如,如果 App 1 的旧密码为
false
prepend de1566cc82d9fda1ac39a28a45afe3671d9ef880
(使用任何旧密码哈希值和新密码哈希值中不会出现的唯一分隔符),使密码列包含类似
app1
并在您的旧密码中检查它是否像
那样app1:::de1566cc82d9fda1ac39a28a45afe3671d9ef880
如前所述,有很多方法可以解决这个问题,显示的只是其中之一,但是这应该提示你通常需要完成这样的任务。
ps,请注意,此处的所有示例代码均未经过测试!
答案 1 :(得分:2)
对于任何对此如何解决的人感到好奇:这就是我所做的,基于ndm的回答。
在该文件夹中,创建一个名为“LegacyPasswordHasher.php”的文件。使用类似于以下代码的代码:
namespace App\Auth;
use Cake\Auth\AbstractPasswordHasher;
class LegacyPasswordHasher extends AbstractPasswordHasher {
public function hash($password) {
throw new \LogicException('You really should not use me!');
// shamelessly copied from ndm's result - a 'hash' function is necessary for this class
}
public function check($password, $hashedPassword) {
// compare using the legacy salt
return sha1('myAwesomeAndStrangeSaltFromPreviousSite'.$password) === $hashedPassword;
}
}
请记住,有些人会添加盐,而其他人会添加盐。确保您知道它是哪个或您的旧版登录无效。
之后,进入你的src / AppController.php文件并在你的public $ components数组下添加:
'authenticate' => [
'Form' => [
'passwordHasher' => [
'className' => 'Fallback',
'hashers' => ['Default', 'Legacy']
// 'Default' is your main one - I added 'Legacy' here
// 'Legacy is called if 'Default' fails - refers to our php file we just made
]
]
]
在此之后,我构建了一个功能,如果用户的密码已过期,则会将用户重定向到密码重置页面。我将所有旧用户导入我的网站,将他们所有的密码到期日期大量设置为多年前,然后通过使用我的旧网站盐加密的密码登录进行测试。它完美地记录了我,检测到我过期的密码,将我重定向到我的“设置新密码”页面,然后在设置新密码后,使用CakePHP 3的当前加密方法对其进行加密(我认为是sha256)。
完美!再次感谢StackOverflow,ndm和互联网。