首頁  >  文章  >  後端開發  >  掌握 Laravel 密碼重設自訂:綜合指南

掌握 Laravel 密碼重設自訂:綜合指南

WBOY
WBOY原創
2024-09-01 06:31:39335瀏覽

Mastering Laravel Password Reset Customization: A Comprehensive Guide

介紹

密碼重設功能是任何現代 Web 應用程式的關鍵元件。雖然 Laravel 提供了強大的開箱即用解決方案,但有時您需要自訂此流程以滿足特定要求或增強使用者體驗。在本教程中,我們將深入探討自訂 Laravel 的密碼重設工作流程,涵蓋從基本修改到進階技術的所有內容。

Laravel 身份驗證簡史

在深入研究客製化之前,讓我們快速回顧一下 Laravel 的身份驗證解決方案是如何演變的:

  1. Laravel UI:Laravel 中完整身份驗證解決方案的第一次迭代,多年來為社區提供了良好的服務。
  2. Laravel Breeze:Breeze 誕生於 Tailwind CSS 的日益流行,提供了一個最小的、輕量級的、現代的身份驗證腳手架。
  3. Laravel Jetstream:對於需要更高級功能的人,引入了 Jetstream,涵蓋了廣泛的身份驗證,包括 2FA 和團隊管理功能。
  4. Laravel Fortify:可與任何前端一起使用的無頭身份驗證後端,為開發人員實現自己的 UI 提供靈活性。

了解 Laravel 的密碼重設流程

Laravel 的密碼重設過程通常涉及以下步驟:

  1. 使用者要求重設密碼
  2. 產生並儲存令牌
  3. 將向使用者發送一封電子郵件,其中包含重置連結(簽名 URL)
  4. 使用者點選連結並輸入新密碼
  5. 密碼已更新,令牌失效

雖然此流程適用於大多數應用程序,但您可能希望自訂此流程的各個方面以更好地滿足您的需求。

我們正在建造什麼

在本教程中,我們將建立一個帶有自訂密碼重設流程的裸 Laravel SaaS(最小)應用程式。我們將涵蓋:

  • 使用 Breeze 設定新的 Laravel 應用程式
  • 自訂密碼重設URL
  • 修改密碼重設郵件內容
  • 新增密碼重設後成功通知
  • 針對我們的變更實施和客製化自動化測試

入門

讓我們開始設定一個新的 Laravel 應用程式:

composer create-project laravel/laravel password-reset-demo
cd password-reset-demo

在繼續之前,讓我們初始化 Git 以進行版本控制:

git init
git add .
git commit -m "Initial commit"

現在,讓我們安裝 Laravel Breeze 來取得基本的驗證鷹架:

composer require laravel/breeze --dev
php artisan breeze:install

出現提示時,選擇最適合您需求的堆疊。在本教程中,我們將使用 Livewire:

php artisan breeze:install

  Which Breeze stack would you like to install?
❯ livewire

  Would you like dark mode support? (yes/no) [no]
❯ no

  Which testing framework do you prefer? [PHPUnit]
❯ Pest

安裝後,讓我們提交更改:

git add .
git commit -m "Add Authentication and Pages"

現在,設定資料庫並執行遷移:

php artisan migrate

安裝並編譯您的前端資源:

npm install
npm run dev

此時,我們已經有了一個具有身份驗證功能的基本 Laravel 應用程式。讓我們執行測試以確保一切按預期工作:

php artisan test

您應該看到所有測試都通過了,為我們繼續進行定制開了綠燈。

自訂密碼重設 URL

預設情況下,Laravel(使用 Breeze)使用標準 URL 進行密碼重設(/reset-password)。讓我們在 AppServiceProvider 中自訂它:

<?php

namespace App\Providers;

use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        ResetPassword::createUrlUsing(function (User $user, string $token) {
            return url(route('password.reset', [
                'token' => $token,
                'email' => $user->getEmailForPasswordReset(),
            ], false));
        });
    }
}

此自訂可讓您修改重設 URL 結構、新增其他參數,甚至根據需要指向完全不同的網域。例如,您可以將其變更為:

return "https://account.yourdomain.com/reset-password?token={$token}&email={$user->getEmailForPasswordReset()}";

修改密碼重設信箱

接下來,讓我們自訂密碼重設電子郵件的內容。我們將透過添加到我們的 AppServiceProvider 來做到這一點:

use Illuminate\Notifications\Messages\MailMessage;

// ...

public function boot(): void
{
    // ... previous customizations

    ResetPassword::toMailUsing(function (User $user, string $token) {
        $url = url(route('password.reset', [
            'token' => $token,
            'email' => $user->getEmailForPasswordReset(),
        ], false));

        return (new MailMessage)
            ->subject(config('app.name') . ': ' . __('Reset Password Request'))
            ->greeting(__('Hello!'))
            ->line(__('You are receiving this email because we received a password reset request for your account.'))
            ->action(__('Reset Password'), $url)
            ->line(__('This password reset link will expire in :count minutes.', ['count' => config('auth.passwords.' . config('auth.defaults.passwords') . '.expire')]))
            ->line(__('If you did not request a password reset, no further action is required.'))
            ->salutation(__('Regards,') . "\n" . config('app.name') . " Team");
    });
}

注意:__() 函數是本地化的助手,可以輕鬆翻譯應用程式中的字串。

新增密碼重設成功通知

為了增強使用者體驗和安全性,讓我們加入在成功重置密碼後發送的通知。首先,建立一個新通知:

php artisan make:notification PasswordResetSuccessfullyNotification

編輯新建立的通知:

<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class PasswordResetSuccessfullyNotification extends Notification implements ShouldQueue
{
    use Queueable;

    public function via($notifiable)
    {
        return ['mail'];
    }

    public function toMail($notifiable)
    {
        return (new MailMessage)
            ->subject('Password Reset Successful')
            ->greeting('Hello!')
            ->line('Your password has been successfully reset.')
            ->line('If you did not reset your password, please contact support immediately.')
            ->action('Login to Your Account', url('/login'))
            ->line('Thank you for using our application!');
    }
}

現在,為PasswordReset事件建立一個監聽器:

php artisan make:listener SendPasswordResetSuccessfullyNotification --event=PasswordReset

更新監聽器:

<?php

namespace App\Listeners;

use App\Notifications\PasswordResetSuccessfullyNotification;
use Illuminate\Auth\Events\PasswordReset;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendPasswordResetSuccessfullyNotification implements ShouldQueue
{
    public function handle(PasswordReset $event)
    {
        $event->user->notify(new PasswordResetSuccessfullyNotification());
    }
}

請記得在您的 EventServiceProvider 中註冊此偵聽器。

測試我們的定制

測試對於確保我們的客製化按預期工作至關重要。更新tests/Feature/Auth/PasswordResetTest.php中現有的密碼重設測試:

<?php

namespace Tests\Feature\Auth;

use App\Models\User;
use App\Notifications\PasswordResetSuccessfullyNotification;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;

class PasswordResetTest extends TestCase
{
    public function test_reset_password_link_can_be_requested(): void
    {
        Notification::fake();

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

        $this->post('/forgot-password', ['email' => $user->email]);

        Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
            $response = $this->get($notification->toMail($user)->actionUrl);
            $this->assertStringContainsString('Reset Password', $response->getContent());
            return true;
        });
    }

    public function test_password_can_be_reset_with_valid_token(): void
    {
        Notification::fake();

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

        $this->post('/forgot-password', ['email' => $user->email]);

        Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
            $token = $notification->token;

            $response = $this->post('/reset-password', [
                'token' => $token,
                'email' => $user->email,
                'password' => 'new-password',
                'password_confirmation' => 'new-password',
            ]);

            $response->assertSessionHasNoErrors();

            Notification::assertSentTo($user, PasswordResetSuccessfullyNotification::class);

            return true;
        });
    }

    public function test_reset_password_email_contains_custom_content(): void
    {
        Notification::fake();

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

        $this->post('/forgot-password', ['email' => $user->email]);

        Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
            $mailMessage = $notification->toMail($user);
            $this->assertStringContainsString('Hello!', $mailMessage->greeting);
            $this->assertStringContainsString('Regards,', $mailMessage->salutation);
            return true;
        });
    }
}

Conclusion

Customizing Laravel's password reset workflow allows you to create a more tailored and user-friendly experience for your application. We've covered how to modify the reset URL, customize the email content, add a success notification, and ensure everything works through automated testing.

Remember, while customization can be powerful, it's essential to maintain security best practices throughout the process. Always validate user input, use secure token generation and storage methods, and follow Laravel's security recommendations.

Some additional considerations for further improvements:

  1. Implement rate limiting on password reset requests to prevent abuse.
  2. Add logging for successful and failed password reset attempts for security auditing.
  3. Consider implementing multi-channel notifications (e.g., SMS, push notifications) for critical security events like password resets.
  4. Regularly review and update your password policies to align with current security best practices.

For more advanced topics and Laravel insights, check out the official Laravel documentation and stay tuned to the Laravel community resources for more in-depth tutorials and best practices.

Happy coding, and may your Laravel applications be ever secure and user-friendly!

以上是掌握 Laravel 密碼重設自訂:綜合指南的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn