Laravel - 如何使用Hash::needsRehash()?

9
我想知道如何使用Hash::needsRehash(),因为我在查看文档时不太清楚它的用途。
if (Hash::needsRehash($hashed)) {
    $hashed = Hash::make('plain-text');
}
Hash::needsRehash()是什么导致它返回true或false?如果哈希密码在另一个哈希中(如MD5、SHA1等),它是否返回true?
如果你的数据库中充满了使用另一种算法的哈希,而Hash::needsRehash()返回true,你该如何重新对用户的密码进行哈希处理,以便使其处于最新状态?你不能依赖“登录”密码,因为需要首先进行比较才能验证,对吗?
我猜可能是我想得太多了,但我现在很困惑。幸运的是,我的用户密码已经使用了password_hash(),所以不应该有问题。
4个回答

4

这似乎是在Laravel 5.6中执行的方法

将以下内容放入LoginController中:

protected function authenticated(Request $request, $user) {
    if (Hash::needsRehash($user->password)) {
        $user->password = Hash::make($request->password);
        $user->save();
    }
}

https://laravel.com/docs/5.6/hashing#basic-usage


4

Hash::needsReHash() 只是调用了php内置的password_needs_rehash函数。文档中有一个有用的注释:

// Check if a newer hashing algorithm is available
// or the cost has changed
if (password_needs_rehash($hash, PASSWORD_DEFAULT, $options)) {

如果哈希算法发生了变化(因为您没有传递任何选项,如成本),Hash::needsReHash()将返回false。

至于何时以及如何使用它,只有在拥有用户密码时才能重新散列其密码--例如,当他们登录时。因此,在登录过程中,您检查其存储的密码算法是否与当前算法不同,如果是,则用新的密码哈希替换其存储的密码哈希。


足够清晰。那么我的另一个担忧仍然存在。如果您当前的用户密码需要重新散列,但是如果您无法验证用户的真实密码,您将如何重新散列它们? - Jean-Luc Tallis
我已经更新了我的回答;你是对的,除非你拥有它,否则无法重新散列一个密码。 - Ben Claar
1
你总是可以验证用户的密码;当PHP存储密码时,它也会存储使用的哈希值。因此,即使哈希值发生更改,PHP也能够验证密码。 - Ben Claar
2
当前成本是否嵌入哈希表中?也就是说,我是否需要另外一个列来存储这个值,还是这一切都是自动处理的? - Cruncher
1
@Cruncher 目前的成本嵌入在 bcrypt 的结果中。这个答案有很好的解释:https://dev59.com/GWw15IYBdhLWcg3wGn5c - cherdt

3
该方法在PHP更新且添加了新的/更好的默认算法或更改了任何其他参数时返回true。这使您可以在不更新代码的情况下自动利用它。
当用户登录时使用此方法,因为这是您唯一可以访问纯文本密码的时间。确认根据旧哈希正确后,您将获取明文密码,重新进行哈希处理,并将其放回数据库以供将来使用。
举个假设性的例子,假设现在算法是md5() 10k次。在PHP7中,它已更新为sha512() 15k次。如果哈希以$count|$algo|$hash格式呈现,则该方法可以告诉您哈希何时过时。由于旧算法未被删除,因此您仍然可以在重新哈希之前通过旧参数验证密码。
注意:显然使用md5()/sha512()是一个坏主意。我只是把它们用作例子。

0

我不知道这里的“use”确切含义是什么,但我根据我的编程经验发现它的一个用途是防止Laravel多次重复哈希密码。这个函数还告诉Laravel不要对已经哈希了的密码再次进行哈希。让我给你举个例子。以前,我在我的Laravel模型中保存密码的代码如下:

public function setPasswordAttribute($password)
    {       
            $this->attributes['password'] = Hash::make($password);
    }

这段代码的作用是:在将密码存储到数据库之前对其进行哈希处理,这样我就不必在控制器的多个函数中调用 make:hash 函数。但我面临的问题是当我使用 Laravel 内置函数时。
public function logoutOtherDevices();

这个函数的作用是对我的密码属性进行重新哈希,但由于我的模型在将密码存储到数据库之前也对其进行了哈希处理,所以会出现双重哈希,导致在使用“注销其他设备”功能后我的密码再也无法正常工作,用户每次都必须使用“忘记密码”功能。现在,当我使用Hash::needsRehash()时,它解决了存储之前的双重哈希问题,密码问题得到了解决。以下是我在模型中实现它的方式。
 public function setPasswordAttribute($password)
    {
        // Check if the given password is already hashed
        if (Hash::needsRehash($password)) {
                // If it is not hashed, hash it before setting the attribute
                $this->attributes['password'] = Hash::make($password);
        } else {
            // If it is already hashed, don't hash it again
            $this->attributes['password'] = $password;
        }
    }

总结:您还可以使用此方法来防止密码被哈希两次,从而可能防止密码错误。这完全基于我的经验。

Laravel文档也尝试建议类似的方法。

https://laravel.com/docs/10.x/hashing#determining-if-a-password-needs-to-be-rehashed


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接