答案:Laravel邮箱验证通过实现MustVerifyEmail接口、添加email_verified_at字段、配置验证路由与中间件、设置邮件服务实现,用户点击签名链接完成验证。

Laravel的邮箱验证功能,说白了,就是给你的用户一个确认身份的机制,确保注册时提供的邮箱是真实有效的。添加这个功能,Laravel其实已经为你铺好了大部分路,你只需要做几步简单的配置和代码调整,就能让它跑起来。核心就是通过发送一个带签名链接的邮件,让用户点击后标记为已验证。
解决方案
在Laravel中添加邮箱验证功能,主要涉及以下几个步骤,它们环环相扣,构成了整个验证流程:
首先,要让你的用户模型知道它需要被验证。这通过实现
Illuminate\Contracts\Auth\MustVerifyEmail
app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable implements MustVerifyEmail // 这里是关键
{
use HasApiTokens, HasFactory, Notifiable;
// ... 其他属性和方法
}接下来,确保你的
users
email_verified_at
create_users_table
php artisan make:migration add_email_verified_at_to_users_table --table=users
然后在生成的迁移文件中添加:
// ...
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->timestamp('email_verified_at')->nullable()->after('email');
});
}
public function down()
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('email_verified_at');
});
}
// ...运行
php artisan migrate
然后,我们需要告诉Laravel哪些路由需要邮箱验证。最简单的方式是在
routes/web.php
Auth::routes(['verify' => true])
use Illuminate\Support\Facades\Auth;
Auth::routes(['verify' => true]);
Route::get('/home', [App\Http\Controllers\HomeController::class, 'index'])
->name('home')
->middleware('verified'); // 确保只有验证过的用户才能访问Auth::routes(['verify' => true])
middleware('verified')最后,也是最关键的一步,是配置你的邮件服务。Laravel默认使用
MAIL_MAILER=smtp
MAIL_HOST
MAIL_PORT
MAIL_USERNAME
MAIL_PASSWORD
MAIL_ENCRYPTION
MAIL_FROM_ADDRESS
MAIL_FROM_NAME
.env
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailtrap.io # 生产环境请替换为真实SMTP服务器
MAIL_PORT=2525
MAIL_USERNAME=null # 替换为你的SMTP用户名
MAIL_PASSWORD=null # 替换为你的SMTP密码
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"完成这些步骤后,当用户注册时,Laravel会自动发送一封验证邮件到其注册邮箱。用户点击邮件中的链接后,
email_verified_at
为什么我的Laravel邮箱验证邮件发不出去?
这是个非常常见的问题,我遇到过不少开发者在邮箱验证功能上线前夕才发现邮件根本发不出去。通常,这背后有几个核心原因,排查起来也有章可循。
首当其冲的,是你的
.env
MAIL_MAILER=log
array
MAIL_HOST
MAIL_PORT
MAIL_USERNAME
MAIL_PASSWORD
MAIL_ENCRYPTION
tls
ssl
587
465
其次,服务器的网络环境也是一个隐形杀手。你的服务器防火墙可能阻止了对外发邮件的端口(通常是
25
465
587
25
再者,如果你的邮件发送是通过队列(Queue)处理的,那么你得确保队列监听器正在运行。很多时候,为了不阻塞用户请求,Laravel会将邮件发送任务推送到队列中。如果你没有启动
php artisan queue:work
php artisan horizon
config/queue.php
MAIL_QUEUE_ENABLED
最后,查看日志文件是解决问题的金钥匙。Laravel会将很多错误信息记录在
storage/logs/laravel.log
当然,还有一些更深层次的问题,比如DNS的SPF和DKIM记录配置不正确,这会导致邮件被标记为垃圾邮件,但通常不会导致邮件完全发不出去,只是收不到。对于生产环境,这些配置也是至关重要的。
如何自定义Laravel邮箱验证通知邮件的样式和内容?
Laravel默认的邮箱验证邮件虽然功能齐全,但样式比较朴素,内容也相对通用。如果你想让验证邮件更符合你的品牌形象,或者添加一些个性化的信息,自定义是完全可行的。
核心思路是覆盖Laravel默认的
VerifyEmail
Illuminate\Auth\Notifications\VerifyEmail
首先,在你的
User
sendEmailVerificationNotification
// app/Models/User.php
use App\Notifications\MyVerifyEmail; // 假设你的自定义通知类在这里
class User extends Authenticatable implements MustVerifyEmail
{
// ...
/**
* Send the email verification notification.
*
* @return void
*/
public function sendEmailVerificationNotification()
{
$this->notify(new MyVerifyEmail());
}
}接下来,创建你自己的
MyVerifyEmail
php artisan make:notification MyVerifyEmail
toMail
VerifyEmail
toMail
// app/Notifications/MyVerifyEmail.php
namespace App\Notifications;
use Illuminate\Auth\Notifications\VerifyEmail as BaseVerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\URL;
class MyVerifyEmail extends BaseVerifyEmail
{
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$verificationUrl = $this->verificationUrl($notifiable);
return (new MailMessage)
->subject('欢迎来到我们的平台!请验证您的邮箱') // 自定义邮件主题
->greeting('您好,' . $notifiable->name . '!') // 自定义问候语
->line('感谢您注册我们的服务。为了确保您的账户安全,请点击下方按钮验证您的邮箱地址。') // 自定义邮件正文
->action('验证邮箱', $verificationUrl) // 自定义按钮文本和链接
->line('如果您没有注册此账户,请忽略此邮件。') // 额外信息
->salutation('祝好,' . config('app.name') . '团队'); // 自定义结束语
}
/**
* Get the verification URL for the given notifiable.
*
* @param mixed $notifiable
* @return string
*/
protected function verificationUrl($notifiable)
{
return URL::temporarySignedRoute(
'verification.verify',
Carbon::now()->addMinutes(config('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
}
}这里我直接复制了
BaseVerifyEmail
verificationUrl
toMail
MailMessage
如果你需要更复杂的HTML邮件模板,你可以创建一个
Mailable
toMail
Mailable
// app/Notifications/MyVerifyEmail.php
// ...
use App\Mail\CustomVerificationMail; // 你的自定义Mailable
class MyVerifyEmail extends BaseVerifyEmail
{
// ...
public function toMail($notifiable)
{
$verificationUrl = $this->verificationUrl($notifiable);
return (new CustomVerificationMail($verificationUrl))
->to($notifiable->email);
}
}
// app/Mail/CustomVerificationMail.php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CustomVerificationMail extends Mailable
{
use Queueable, SerializesModels;
public $verificationUrl;
public function __construct($verificationUrl)
{
$this->verificationUrl = $verificationUrl;
}
public function build()
{
return $this->subject('请验证您的邮箱地址')
->markdown('emails.verify-email') // 指向你的Blade模板
->with([
'url' => $this->verificationUrl,
'userName' => $this->to[0]['name'] ?? '用户', // 假设你可以获取到用户名
]);
}
}然后创建一个
resources/views/emails/verify-email.blade.php
在API应用中,Laravel邮箱验证应该如何实现?
在API应用中实现邮箱验证,与传统Web应用有所不同,因为API通常不涉及重定向和Session管理,而是通过JSON响应和Token认证进行交互。核心挑战在于如何处理验证链接的点击,以及如何将验证状态反馈给前端应用。
首先,
MustVerifyEmail
email_verified_at
当用户注册后,你可以通过API返回一个成功的响应,并在后台触发邮件发送。邮件内容中包含的验证链接,不应该指向传统的Web路由,而应该指向一个专门用于API验证的端点。
假设你的前端应用是一个SPA (Single Page Application) 或移动应用:
修改验证链接的生成逻辑: 在
User
MyVerifyEmail
verificationUrl
例如,如果你的前端验证页面是
https://your-frontend.com/verify-email?signature=...&expires=...&id=...&hash=...
// app/Notifications/MyVerifyEmail.php
// ...
protected function verificationUrl($notifiable)
{
// 假设你的前端验证页面URL
$frontendVerificationUrl = config('app.frontend_url') . '/verify-email';
return URL::temporarySignedRoute(
'verification.verify.api', // 这是一个你自定义的API验证路由名称
Carbon::now()->addMinutes(config('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
'redirect' => $frontendVerificationUrl, // 将前端URL作为参数传递
]
);
}这里
config('app.frontend_url').env
创建API验证路由和控制器: 在
routes/api.php
// routes/api.php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\Api\EmailVerificationController;
Route::get('/email/verify/{id}/{hash}', [EmailVerificationController::class, 'verify'])
->middleware(['auth:sanctum', 'signed']) // 使用 'signed' 中间件验证URL签名
->name('verification.verify.api');
Route::post('/email/resend', [EmailVerificationController::class, 'resend'])
->middleware(['auth:sanctum', 'throttle:6,1'])
->name('verification.resend.api');注意这里的
auth:sanctum
signed
signed
实现API验证控制器: 在
app/Http/Controllers/Api/EmailVerificationController.php
verify
// app/Http/Controllers/Api/EmailVerificationController.php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Illuminate\Auth\Access\AuthorizationException;
class EmailVerificationController extends Controller
{
public function verify(Request $request, User $user)
{
// 检查URL的ID和哈希是否匹配
if (! hash_equals((string) $request->route('id'), (string) $user->getKey())) {
throw new AuthorizationException;
}
if (! hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) {
throw new AuthorizationException;
}
// 检查用户是否已经验证过
if ($user->hasVerifiedEmail()) {
// 如果已经验证,可以返回一个成功响应,或者重定向到前端的某个页面
return response()->json(['message' => 'Email already verified.'], 200);
}
// 执行验证
if ($user->markEmailAsVerified()) {
event(new Verified($user));
}
// 验证成功,返回JSON响应
return response()->json(['message' => 'Email verified successfully.'], 200);
}
public function resend(Request $request)
{
$user = $request->user();
if ($user->hasVerifiedEmail()) {
return response()->json(['message' => 'Email already verified.'], 400);
}
$user->sendEmailVerificationNotification();
return response()->json(['message' => 'Verification link resent.'], 200);
}
}这里,当用户点击邮件中的链接时,请求会打到这个
verify
id
hash
signature
verification.verify.api
前端处理: 前端应用需要有一个专门的页面或组件来处理验证链接。当用户点击邮件中的链接,如果链接指向前端应用,前端需要:
id
hash
signature
verification.verify.api
这种方式将验证逻辑完全放在后端API中,前端只负责触发和展示结果,保持了前后端分离的原则。
以上就是Laravel邮箱验证?验证功能如何添加?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号