解密 Laravel 密码重置令牌

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41862370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 15:11:55  来源:igfitidea点击:

Decrypt Laravel Password Reset Token

phplaravelunit-testinglaravel-5.3laravel-5.4

提问by Denis Priebe

I am writing a test that ensures that the password reset functionality of my application works. The password reset system was created using the php artisan make:authcommand. In order to make the test pass I need to automate a GET request to /password/reset/{$token}where $tokenis the value stored in the password_resetstable. Laravel stores the token like this:

我正在编写一个测试,以确保我的应用程序的密码重置功能正常工作。密码重置系统是使用该php artisan make:auth命令创建的。为了使测试通过我需要自动化的GET请求来/password/reset/{$token}这里$token是存储在值password_resets表。Laravel 像这样存储令牌:

$2y$10$9grKb3c6.Toiv0kjUWbCUeT8Q8D.Fg2gZ/xDLGQUAkmdyHigmRkNW

$2y$10$9grKb3c6.Toiv0kjUWbCUeT8Q8D.Fg2gZ/xDLGQUAkmdyHigmRkNW

but when Laravel sends the password reset email to the user, the reset token looks like this in the email:

但是当 Laravel 向用户发送密码重置邮件时,邮件中的重置令牌如下所示:

382aa64567ecd05a774c2e4ebb199d3340a1424300707053354c749c10487594.

382aa64567ecd05a774c2e4ebb199d3340a1424300707053354c749c10487594.

My GET request to /password/reset/$2y$10$9grKb3c6.Toiv0kjUWbCUeT8Q8D.Fg2gZ/xDLGQUAkmdyHigmRkNWfails due to the forward slash in the reset token. (Right after the 'g2gZ')

/password/reset/$2y$10$9grKb3c6.Toiv0kjUWbCUeT8Q8D.Fg2gZ/xDLGQUAkmdyHigmRkNW由于重置令牌中的正斜杠,我的 GET 请求失败。(在 'g2gZ' 之后

I tried using the helper function decrypt()but had no luck.

我尝试使用辅助函数decrypt()但没有运气。

How can I convert the password reset token I pull from the password_resetstable to match what Laravel sends to the user?

如何转换我从password_resets表中提取的密码重置令牌以匹配 Laravel 发送给用户的内容?

Not sure if this is relevant but I did upgrade my application from 5.3 to 5.4.

不确定这是否相关,但我确实将我的应用程序从 5.3 升级到 5.4。

回答by pinguinjkeke

You can get token from closure used for additional checks passed to Notification's assertSentTo method because $tokenis a public property of standard ResetPasswordnotification.

您可以从用于传递给 Notification 的 assertSentTo 方法的附加检查的闭包中获取令牌,因为它$token是标准ResetPassword通知的公共属性。

In your test:

在您的测试中:

Notification::fake();

$this->postJson('api/user/reset', ['email' => $user->email])
    ->assertStatus(200);

$token = '';

Notification::assertSentTo(
    $this->user,
    \Illuminate\Auth\Notifications\ResetPassword::class,
    function ($notification, $channels) use (&$token) {
        $token = $notification->token;

        return true;
    });

$this->postJson('api/user/resetting', [
    'email' => $user->email,
    'token' => $token,
    'password' => '87538753',
    'password_confirmation' => '87538753'
])
    ->assertStatus(200);

回答by BrokenBinary

The token stored in the password_resetstable is hashed just like a normal password, so you can't reverse it to get the original token.

存储在password_resets表中的令牌就像普通密码一样经过哈希处理,因此您无法将其反转以获取原始令牌。

I suggest that you use the logmail driverwhen running tests. Then the password reset email will be printed in plain text in the laravel log and you can grab the token from that.

我建议您在运行测试时使用log邮件驱动程序。然后密码重置电子邮件将以纯文本形式打印在 laravel 日志中,您可以从中获取令牌。

回答by Justin MacArthur

I don't think you can, the hash that's saved is a bcrypted value of a sha256 hash of a random 40 digit number. which means it's not reversible just one way checkable.

我认为你不能,保存的散列是一个随机 40 位数字的 sha256 散列的 bcrypted 值。这意味着它不是可逆的,只能通过一种方式检查。

回答by superfly

For testing the password reset functionality, I replace the generated token from the password_resettable with a new one.

为了测试密码重置功能,我将password_reset表中生成的令牌替换为一个新令牌。

The reset token is created with the createTokenRepository()method - laravel/framework/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php

使用以下createTokenRepository()方法创建重置令牌-laravel/framework/src/Illuminate/Auth/Passwords/PasswordBrokerManager.php

For hashing the created token, Laravel uses the make()method - laravel/framework/src/Illuminate/Hashing/BcryptHasher.php

为了散列创建的令牌,Laravel 使用make()方法 -laravel/framework/src/Illuminate/Hashing/BcryptHasher.php

public function test_it_should_reset_the_password()
{

    Mail::fake();

    $user = factory(App\User::class)->create();

    $response = $this->json('POST', 'api/password/email',
                    [
                        'email' => $user->email
                    ]);
    $response->assertStatus(202);

    Mail::hasSent($user, ResetPassword::class);

    // Since we don't know the emailed token from 
    // the previous JSON call, we're
    // gonna replace the token with a new one
    $token = hash_hmac('sha256', Str::random(40), $user);
    DB::table('password_resets')
            ->where('email', $user->email)
            ->update([
                'token' => password_hash($token, PASSWORD_BCRYPT, ['cost' => '10'])
            ]);

    $response = $this->json('POST', 'api/password/reset', [
                    'email'                 => $user->email,
                    'password'              => 'new_user_password',
                    'password_confirmation' => 'new_user_password',
                    'token'                 => $token
                ]);
    $response->assertStatus(202);

    $response = $this->json('POST', 'api/login',
                    [
                        'email' => $user->email,
                        'password' => 'new_user_password'
                    ]);
    $response->assertStatus(202);
    // check for JWT token
    $response->assertJson(['token' => true]);

}