将旧密码迁移到CakePHP 3

Isa*_*kew 6 passwords algorithm hash salt cakephp-3.0

我读的蛋糕3网站上的验证文件在这里,我仍然对如何我的用户密码迁移到我的新的应用程序略有困惑.

它说要包含FallbackPasswordHasher类,但如果是这种情况,我在哪里放置旧密码的盐(因为新网站不同)?除此之外,一切似乎都是不言自明的.

我有几个不同但相关的网站,我正在整合到一个网站,将在多个企业提供相同的服务,所以我需要从不同的网站导入用户的密码.

ndm*_*ndm 7

这取决于使用的旧散列机制

根据所使用的机制和算法,您可能不需要旧的盐,因为它已经附加到散列,例如,使用Blowfish密码hasher 进行哈希处理的密码,或者通常使用密码进行哈希处理crypt(),可以验证它们通过Default密码hasher.

因此,如果所有密码都是这种情况,那么您根本不需要使用Fallback密码密码,而是只使用Default密码密码,并在必要时重新密码,如文档中所示.


没有附盐的哈希

对于使用没有盐重视哈希,例如像机制哈希密码md5(),sha1(),mhash()等,你可能需要一个整合了已使用旧密码的盐的自定义传统的密码散列器.

在大多数情况下,WeakPasswordhasher应该完成这项工作,它使用旧的Cake 2机制和salt配置,即全局Security.salt选项和hashTypehasher选项.

请参阅Cookbook> Authentication>更改散列算法

如果你的弱应用程序不适合你,因为你已经在你的旧应用程序中使用了自定义哈希,那么你将需要一个自定义的传统哈希.可以在文档中找到遗留密码哈希的示例,并且合并盐应该是例如简单的

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

请注意,在使用Fallbackhasher的情况下,传统的hasher不需要实现hash()实际哈希的东西,因为你不应该将它用于新的哈希.


每个应用程序的不同盐和/或算法

使用来自使用单个盐的不同来源的密码可能会使事情变得更复杂.

有多种方法可以解决这个问题,而最明显的方法(因为这就是Fallback哈希的工作方式)是为每个应用创建一个单独的自定义传统哈希,其中不同的哈希将使用适当的盐,也可能特定应用程序的算法.

您需要做的就是依靠Fallbackhasher迭代所有遗留的哈希,直到其中一个成功验证密码.

'passwordHasher' => [
    'className' => 'Fallback',
    'hashers' => ['Default', 'LegacyApp1', 'LegacyApp2', 'LegacyApp3', /* ... */]
]
Run Code Online (Sandbox Code Playgroud)

就这样?

基本上,是的,这里唯一的问题可能是冲突,即App X的哈希将成功验证通常false由密码来源的App Y的哈希评估的密码.

如果这种情况可能出于某种原因(即使对于那么弱的MD5,它通常也不太可能),你必须寻求更严格的解决方案.

可能有10 ^ Cake方法可以解决这样的问题,所以由于碰撞应该不太可能,我会坚持认为最基本的方法,即在合并密码之前修改密码,以便它们具有标识符添加标识旧应用程序,然后可以由旧密码hasher使用它来选择适当的salt和算法.

一个例子

例如,如果App 1的旧密码是

de1566cc82d9fda1ac39a28a45afe3671d9ef880
Run Code Online (Sandbox Code Playgroud)

prepend app1(使用一个不能出现在任何旧密码和新密码哈希中的唯一分隔符)来使密码列包含类似的内容

app1:::de1566cc82d9fda1ac39a28a45afe3671d9ef880
Run Code Online (Sandbox Code Playgroud)

并在您的旧密码中检查它是否正在做类似的事情

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;
}
Run Code Online (Sandbox Code Playgroud)

如前所述,有很多方法可以解决这个问题,显示的只是其中之一,但是这应该提示您通常需要完成这样的任务.


ps,请注意这里的所有示例代码都是未经测试的!