我正在阅读 Cake 3 网站上的 Auth 文档here ,我仍然对如何将我的用户的密码迁移到我的新应用程序有点困惑。
它说要包含 FallbackPasswordHasher 类,但如果是这种情况,我应该将旧密码的盐放在哪里(因为新站点的情况不同)?除此之外,一切似乎都是不言自明的。
我有几个不同但相关的网站,我将它们整合到一个网站中,这些网站将在多个企业中提供相同的服务,因此我需要从使用不同盐的各种网站导入用户的密码。
最佳答案
这取决于使用的旧哈希机制
根据所使用的机制和算法,您可能不需要旧的 salt,因为它已经附加到散列,例如,使用 Blowfish
密码散列器散列的密码就是这种情况,或者通常使用 crypt()
散列的密码,它们可以由 Default
密码哈希器验证。
因此,如果您的所有密码都是这种情况,那么您根本不需要使用 Fallback
密码哈希器,而可以仅使用 Default
密码哈希器,并在必要时重新哈希密码 as shown in the docs 。
不加盐的哈希
对于使用不将盐附加到散列的机制进行散列的密码,例如 md5()
、 sha1()
、 mhash()
等,您可能需要一个自定义的旧密码散列器,其中包含已用于旧密码的盐。
在大多数情况下,WeakPassword
hasher 应该完成这项工作,它使用旧的 Cake 2 机制和 salt 配置,即全局 Security.salt
选项和 hashType
hasher 选项。
见 Cookbook > Authentication > Changing Hashing Algorithms
如果弱散列器对您不起作用,因为例如您在旧应用程序中使用了自定义散列器,那么您将需要一个自定义旧散列器。旧密码散列器 can be found in the docs 的示例,加入盐应该像示例一样简单
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()
来实际散列某些东西,因为您不应该将它用于新的散列。每个应用程序不同的盐和/或算法
拥有来自不同来源的密码,其中使用了单独的盐,可能会使事情变得更加复杂。
有多种方法可以解决这个问题,最明显的方法(因为这就是
Fallback
哈希器的工作方式)是为每个应用程序创建一个单独的自定义遗留哈希器,不同的哈希器将使用适当的盐,也许还有特定应用程序的算法。然后您需要做的就是依靠
Fallback
哈希器迭代所有旧哈希器,直到其中一个成功验证密码。'passwordHasher' => [
'className' => 'Fallback',
'hashers' => ['Default', 'LegacyApp1', 'LegacyApp2', 'LegacyApp3', /* ... */]
]
就这样?
基本上,是的,这里唯一的问题可能是冲突,即 App X 的哈希器将成功验证密码,该密码通常会被哈希器评估为
false
的 App Y 的密码来自何处。如果这是一种可能出于任何原因的情况(即使对于非常弱的 MD5,通常也不太可能发生),您必须寻求更严格的解决方案。
可能有 10^Cake 方法来解决这样的问题,所以由于冲突应该是不太可能的,我会坚持我认为最基本的方法,那就是在合并密码之前修改密码,以便它们有一个标识符添加了标识旧应用程序的功能,然后旧密码哈希器可以使用它来选择适当的盐和算法。
一个例子
例如,如果 App 1 的旧密码是
de1566cc82d9fda1ac39a28a45afe3671d9ef880
在
app1
前面加上一个唯一的分隔符,这个分隔符不能出现在任何旧的和新的密码哈希中)使密码列包含类似的内容app1:::de1566cc82d9fda1ac39a28a45afe3671d9ef880
并在您的旧密码哈希器中检查它是否执行类似的操作
public function check($password, $hashedPassword) {
if(strpos($hashedPassword, ':::') === false) {
// this is not the password you are looking for
return false;
}
// separate the identifier from the password
list($app, $hashedPassword) = explode(':::', $hashedPassword, 2);
// create comparision hash using app specific legacy algorithms and salts
switch($app) {
case 'app1':
$compare = sha1($password . '375828236784563245364');
break;
case 'app2':
$compare = md5('legacy-salt-for-app-2' . $password);
break;,
// etc
default:
return false;
}
return $compare === $hashedPassword;
}
正如最初提到的,有很多方法可以解决这个问题,显示的方法只是其中之一,但是这应该会提示您完成此类任务通常需要什么。
ps,请注意这里所有的示例代码都是未经测试的!
关于algorithm - 将旧密码迁移到 CakePHP 3,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27336798/