7

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

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

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

382aa64567ecd05a774c2e4ebb199d3340a1424300707053354c749c10487594.

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

我尝试使用辅助功能decrypt(),但没有运气。

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

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

4

4 回答 4

12

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

在您的测试中:

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);
于 2017-03-04T12:11:50.447 回答
4

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

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

于 2017-01-25T22:20:13.247 回答
1

我不认为你可以,保存的哈希是随机 40 位数字的 sha256 哈希的 bcrypted 值。这意味着它不可逆,只有一种可检查的方式。

于 2017-01-25T22:21:45.910 回答
1

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

重置令牌是使用以下createTokenRepository()方法创建的 -laravel/framework/src/Illuminate/Auth/Passwords/PasswordBrokerManager.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]);

}
于 2017-03-04T10:36:32.030 回答