
本文详细介绍了在 Laravel 应用中实现灵活邮箱验证的策略。通过创建自定义中间件,我们能够确保所有已登录用户在访问网站任何页面前必须完成邮箱验证,同时允许未登录访客自由浏览公共内容,解决了标准 `verified` 中间件的局限性,实现了兼顾用户体验与安全性的邮箱验证流程。
在 Laravel 应用程序开发中,邮箱验证是确保用户身份真实性和安全性的重要环节。Laravel 提供了开箱即用的邮箱验证功能,并通过 verified 中间件来保护需要验证的路由。然而,在某些场景下,我们可能面临一个特殊需求:网站的某些页面允许访客(未登录用户)访问,但一旦用户登录,无论访问任何页面(包括那些访客可访问的公共页面),都必须先完成邮箱验证。
Laravel 内置的 verified 中间件在此场景下存在局限性。它首先会检查用户是否已认证(即是否已登录),如果用户未登录,它会直接将请求重定向到登录页面,从而阻止访客访问公共页面。这与我们“访客可访问,登录用户强制验证”的需求相悖。为了解决这一问题,我们需要创建一个自定义中间件。
Laravel 的 verified 中间件(对应的类是 Illuminate\Auth\Middleware\EnsureEmailIsVerified)的核心逻辑是:
正是第四点行为,导致我们无法将 verified 中间件直接应用于访客可访问的公共路由,因为它会强制访客登录。
为了实现我们的目标,我们需要一个能够区分访客和已登录用户的中间件。这个中间件的逻辑应该如下:
首先,通过 Artisan 命令创建一个新的中间件:
php artisan make:middleware EnsureEmailIsVerifiedUnlessGuest
这会在 app/Http/Middleware 目录下生成 EnsureEmailIsVerifiedUnlessGuest.php 文件。编辑该文件,修改其 handle 方法如下:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\URL;
class EnsureEmailIsVerifiedUnlessGuest
{
/**
* 处理传入的请求。
*
* @param \Illuminate\Http\Request $request
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
* @param string|null $redirectToRoute
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse|null
*/
public function handle($request, Closure $next, $redirectToRoute = null)
{
// 检查用户是否已认证,并且是否需要进行邮箱验证
// $request->user() 为 null 表示用户未登录(访客),此时直接放行
if ($request->user() &&
($request->user() instanceof MustVerifyEmail &&
! $request->user()->hasVerifiedEmail())) {
// 如果用户已登录但邮箱未验证,则重定向到验证通知页面
return $request->expectsJson()
? abort(403, '您的邮箱地址尚未验证。')
: Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));
}
// 用户未登录、或已登录且邮箱已验证,则允许请求继续
return $next($request);
}
}
代码解析:
创建完自定义中间件后,需要将其注册到 app/Http/Kernel.php 文件的 $routeMiddleware 数组中,以便可以在路由中使用简短的别名。
打开 app/Http/Kernel.php 文件,在 $routeMiddleware 数组中添加一行:
// app/Http/Kernel.php
protected $routeMiddleware = [
// ... 其他中间件
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \App\Http\Middleware\EnsurePasswordIsConfirmed::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// 注册我们自定义的中间件
'verified-or-guest' => \App\Http\Middleware\EnsureEmailIsVerifiedUnlessGuest::class,
];现在,你可以在你的路由定义中使用 verified-or-guest 这个别名了。为了满足“所有已登录用户在访问网站任何页面前必须完成邮箱验证”的需求,你应该将这个中间件应用到你网站的大部分或所有路由组上,或者至少是那些可能被已登录用户访问的路由。
示例:应用到路由
use Illuminate\Support\Facades\Route;
// 访客和已登录用户都可以访问的公共页面
Route::get('/', function () {
return view('welcome');
})->middleware('verified-or-guest'); // 应用自定义中间件
Route::get('/posts/{id}', function ($id) {
return "This is post " . $id;
})->middleware('verified-or-guest'); // 应用自定义中间件
// 对于需要登录才能访问的页面,你也可以使用它,或者结合 'auth' 中间件
Route::middleware(['auth', 'verified-or-guest'])->group(function () {
Route::get('/dashboard', function () {
return view('dashboard');
});
// ... 其他需要认证和验证的路由
});通过这种方式,当访客访问 / 或 /posts/1 时,verified-or-guest 中间件会检测到没有认证用户,直接放行。而当一个已登录但未验证邮箱的用户访问这些页面时,他们将被重定向到邮箱验证通知页面。
通过创建 EnsureEmailIsVerifiedUnlessGuest 这样的自定义中间件,我们成功地解决了 Laravel 中邮箱验证的特定场景需求:既允许访客自由访问公共内容,又强制所有已登录用户在访问网站任何部分前完成邮箱验证。这种方法提供了极大的灵活性,使得开发者能够更好地平衡用户体验、安全性和业务逻辑。遵循本文的步骤,你将能够轻松地在你的 Laravel 应用中实现这一高级的邮箱验证策略。
以上就是Laravel 中实现访客友好且强制登录用户邮箱验证的策略的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号