logo

密码确认

简介

在构建应用程序时,你可能偶尔会遇到在执行操作之前需要用户确认其密码的操作。例如,Jetstream 本身要求用户在更改其双因素身份验证设置之前确认其密码。值得庆幸的是,Jetstream 具有内置功能,可以轻松实现这一点。

Jetstream 提供了两种密码确认方法:基于重定向的密码确认和基于模态的密码确认。

基于重定向的密码确认

基于重定向的密码确认通常在用户需要在访问应用程序呈现的整个屏幕(例如计费设置屏幕)之前确认其密码时使用。

这种形式的密码确认会将用户重定向到一个专门的密码确认屏幕,在该屏幕中,他们必须确认其密码,然后才能重定向到其预期目的地。

基于模态的密码身份验证可能在希望用户在执行特定操作(例如启用双因素身份验证)之前确认其密码时使用。

这种形式的密码确认会显示一个模态窗口,允许用户在执行其预期请求之前确认其密码。

重定向密码确认

以下文档将讨论如何在 Jetstream 中使用基于重定向的密码确认。基于重定向的密码确认通常在用户需要在访问应用程序呈现的整个屏幕(例如计费设置屏幕)之前确认其密码时使用。

这种形式的密码确认会将用户重定向到一个专门的密码确认屏幕,在该屏幕中,他们必须确认其密码,然后才能重定向到其预期目的地。

Screenshot of Password Confirmation

通过 Livewire 重定向密码确认

保护路由

要通过重定向到密码确认屏幕实现密码确认,你应确保将呈现需要密码确认的视图的路由以及执行已确认操作的任何路由分配给 password.confirm 中间件。

此中间件包含在 Laravel 的默认安装中,如果用户尝试在不确认密码的情况下访问路由,它将确保用户被重定向到应用程序的密码确认屏幕

php
Route::get('/billing', function () {
    // ...
})->middleware(['password.confirm']);

Route::post('/billing', function () {
    // ...
})->middleware(['password.confirm']);

呈现 Livewire 堆栈密码确认屏幕的视图位于 resources/views/auth/confirm-password.blade.php。通常情况下,此视图不需要自定义;但是,你可以根据自己的应用程序设计对该页面进行常规展示调整。

确保密码确认

接下来,包含在调用之前应要求密码确认的操作的 Livewire 组件应使用 Laravel\Jetstream\ConfirmsPasswords 特性。

将此特性添加到组件后,你应在需要密码确认的任何 Livewire 操作中调用 ensurePasswordIsConfirmed 方法。这应在相关操作方法的开头完成

php
/**
 * Enable administration mode for user.
 */
public function enableAdminMode(): void
{
    $this->ensurePasswordIsConfirmed();

    // ...
}

密码确认过期

一旦用户确认其密码,在应用程序的 auth.password_timeout 配置选项定义的秒数过去之前,将不需要重新输入密码

通过 Inertia 重定向密码确认

要通过重定向到密码确认屏幕实现密码确认,你应确保将呈现需要密码确认的视图的路由以及执行已确认操作的任何路由分配给 password.confirm 中间件。

此中间件包含在 Laravel 的默认安装中,如果用户尝试在不确认密码的情况下访问路由,它将确保用户被重定向到应用程序的密码确认屏幕

php
Route::get('/billing', function () {
    // ...
})->middleware(['password.confirm']);

Route::post('/billing', function () {
    // ...
})->middleware(['password.confirm']);

呈现 Inertia 堆栈密码确认屏幕的页面位于 resources/js/Pages/Auth/ConfirmPassword.vue。通常情况下,此页面不需要自定义;但是,你可以根据自己的应用程序设计对该页面进行常规展示调整。

密码确认过期

一旦用户确认其密码,在应用程序的 auth.password_timeout 配置选项定义的秒数过去之前,将不需要重新输入密码。

以下文档将讨论如何在 Jetstream 中使用基于模态框的密码确认。基于模态框的密码验证通常在希望用户在执行特定操作(例如启用双重身份验证)之前确认其密码时使用。

这种形式的密码确认会显示一个模态窗口,允许用户在执行其预期请求之前确认其密码。

Screenshot of Password Confirmation

组件准备

如果您正在使用 Livewire 栈,则包含在调用前需要密码确认的操作的 Livewire 组件应使用 Laravel\Jetstream\ConfirmsPasswords 特征。

confirms-password Blade 组件

接下来,在应用程序的用户界面中,您应将触发操作的按钮包装在 confirms-password Blade 组件内。confirms-password 包装组件应包含一个 wire:then 指令,该指令指定在用户密码得到确认后应运行哪个 Livewire 操作

html
<x-confirms-password wire:then="enableAdminMode">
    <x-button type="button" wire:loading.attr="disabled">
        {{ __('Enable') }}
    </x-button>
</x-confirms-password>

通过 Livewire 确保密码确认

confirms-password 组件添加到应用程序的用户界面后,您应在需要密码确认的 Livewire 操作中调用 ensurePasswordIsConfirmed 方法。这应在相关操作方法的开头完成

php
/**
 * Enable administration mode for user.
 */
public function enableAdminMode(): void
{
    $this->ensurePasswordIsConfirmed();

    // ...
}

密码确认过期

一旦用户确认其密码,在应用程序的 auth.password_timeout 配置选项定义的秒数过去之前,将不需要重新输入密码。

ConfirmsPassword Vue 组件

如果您正在使用 Inertia 栈,则您应该使用 Jetstream 提供的 ConfirmsPassword Vue 组件包装触发需要密码确认操作的用户界面元素。要开始,请将 ConfirmsPassword 组件导入到您的页面

js
import ConfirmsPassword from './Components/ConfirmsPassword.vue'

接下来,使用 ConfirmsPassword 组件包装触发应确认的操作的用户界面元素。您的页面应侦听 ConfirmsPassword 组件的 @confirmed 事件,以便在用户密码得到确认后触发应调用的方法

html
<ConfirmsPassword @confirmed="enableAdminMode">
    <PrimaryButton type="button" :class="{ 'opacity-25': enabling }" :disabled="enabling">
        Enable
    </PrimaryButton>
</ConfirmsPassword>

通过 Inertia 确保密码确认

ConfirmsPassword 组件添加到用户界面后,您应确保执行确认操作的路由被分配了 password.confirm 中间件。此中间件包含在 Laravel 的默认安装中

php
Route::post('/admin-mode', function () {
    // ...
})->middleware(['password.confirm']);

密码确认过期

一旦用户确认其密码,在应用程序的 auth.password_timeout 配置选项定义的秒数过去之前,将不需要重新输入密码

自定义确认密码的方式

有时,您可能希望在确认期间自定义验证用户密码的方式。为此,您可以使用 Fortify::confirmPasswordsUsing 方法。此方法接受一个闭包,该闭包接收经过身份验证的用户实例和请求的 password 输入字段。如果密码对给定用户有效,则闭包应返回 true。通常,此方法应从 JetstreamServiceProviderboot 方法中调用

php
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Laravel\Fortify\Fortify;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    // ...

    Fortify::confirmPasswordsUsing(function (User $user, string $password) {
        return Hash::check($password, $user->password);
    });
}

如果您希望将密码确认过程封装在类中而不是闭包中,则可以将 PHP “可调用”数组传递给 confirmPasswordsUsing 方法

php
use App\Actions\ConfirmPassword;
use Laravel\Fortify\Fortify;

Fortify::confirmPasswordsUsing([new ConfirmPassword, '__invoke']);