首页 > php框架 > Laravel > 正文

Laravel邮箱验证?验证功能如何添加?

月夜之吻
发布: 2025-09-16 09:21:01
原创
541人浏览过
答案:Laravel邮箱验证通过实现MustVerifyEmail接口、添加email_verified_at字段、配置验证路由与中间件、设置邮件服务实现,用户点击签名链接完成验证。

laravel邮箱验证?验证功能如何添加?

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
登录后复制
字段。这个字段是用来存储用户邮箱验证成功的时间戳的。如果你是新项目,Laravel自带的
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
登录后复制
变量。例如,使用 Mailgun 或 SES 会更稳定可靠。

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
登录后复制
调试得好好的,一上生产环境就忘了改成真实的 SMTP 配置,或者填错了服务器地址、端口、用户名和密码。
MAIL_HOST
登录后复制
MAIL_PORT
登录后复制
MAIL_USERNAME
登录后复制
MAIL_PASSWORD
登录后复制
这些参数,只要有一个不对,邮件就飞不出去。特别是端口和加密方式(
MAIL_ENCRYPTION
登录后复制
),不同服务商要求可能不同,比如有些是
tls
登录后复制
,有些是
ssl
登录后复制
,端口也可能是
587
登录后复制
465
登录后复制
。务必仔细核对你的邮件服务提供商(比如Gmail, Mailgun, SendGrid, AWS SES等)提供的配置信息。

其次,服务器的网络环境也是一个隐形杀手。你的服务器防火墙可能阻止了对外发邮件的端口(通常是

25
登录后复制
,
465
登录后复制
,
587
登录后复制
)。如果你在云服务器上部署,检查一下安全组或防火墙规则,确保这些端口是开放的。有时候,ISP(互联网服务提供商)或者云服务商本身也会限制默认的
25
登录后复制
端口,以防止垃圾邮件。这种情况下,你可能需要换一个端口或者使用一个专用的邮件API服务。

再者,如果你的邮件发送是通过队列(Queue)处理的,那么你得确保队列监听器正在运行。很多时候,为了不阻塞用户请求,Laravel会将邮件发送任务推送到队列中。如果你没有启动

php artisan queue:work
登录后复制
或者
php artisan horizon
登录后复制
,那么这些邮件任务就一直躺在队列里,永远不会被发送出去。检查一下你的
config/queue.php
登录后复制
配置,以及
MAIL_QUEUE_ENABLED
登录后复制
(如果自定义了)等变量。

最后,查看日志文件是解决问题的金钥匙。Laravel会将很多错误信息记录在

storage/logs/laravel.log
登录后复制
文件中。如果邮件发送失败,这里通常会有详细的错误堆栈信息,比如连接超时、认证失败、邮件地址无效等等。仔细阅读这些日志,往往能直接指出问题所在。

当然,还有一些更深层次的问题,比如DNS的SPF和DKIM记录配置不正确,这会导致邮件被标记为垃圾邮件,但通常不会导致邮件完全发不出去,只是收不到。对于生产环境,这些配置也是至关重要的。

如何自定义Laravel邮箱验证通知邮件的样式和内容?

AI-Text-Classifier
AI-Text-Classifier

OpenAI官方出品,可以区分人工智能书写的文本和人类书写的文本

AI-Text-Classifier 59
查看详情 AI-Text-Classifier

Laravel默认的邮箱验证邮件虽然功能齐全,但样式比较朴素,内容也相对通用。如果你想让验证邮件更符合你的品牌形象,或者添加一些个性化的信息,自定义是完全可行的。

核心思路是覆盖Laravel默认的

VerifyEmail
登录后复制
通知类。Laravel在发送验证邮件时,实际上是触发了一个
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
登录后复制
方法,来构建你的邮件内容。最简单的方式是继承Laravel自带的
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
登录后复制
模板,用HTML和Blade语法来设计你的邮件。这样就能够完全掌控邮件的视觉呈现了。

在API应用中,Laravel邮箱验证应该如何实现?

在API应用中实现邮箱验证,与传统Web应用有所不同,因为API通常不涉及重定向和Session管理,而是通过JSON响应和Token认证进行交互。核心挑战在于如何处理验证链接的点击,以及如何将验证状态反馈给前端应用。

首先,

MustVerifyEmail
登录后复制
接口和
email_verified_at
登录后复制
字段依然是基础,这些后端逻辑是通用的。

当用户注册后,你可以通过API返回一个成功的响应,并在后台触发邮件发送。邮件内容中包含的验证链接,不应该指向传统的Web路由,而应该指向一个专门用于API验证的端点。

假设你的前端应用是一个SPA (Single Page Application) 或移动应用:

  1. 修改验证链接的生成逻辑:

    User
    登录后复制
    模型中,或者你自定义的
    MyVerifyEmail
    登录后复制
    通知类中,你需要修改
    verificationUrl
    登录后复制
    方法,使其生成的链接指向你的前端应用的一个特定路由,并且这个路由会带上Laravel生成的签名验证参数。

    例如,如果你的前端验证页面是

    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
    登录后复制
    中定义的前端应用的基URL。

  2. 创建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
    登录后复制
    中间件会检查URL的签名是否有效且未过期。

  3. 实现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
    登录后复制
    API端点。前端应用在收到邮件后,用户点击链接,如果这个链接被配置为打开前端应用的某个页面,那么前端应用需要解析URL参数(
    id
    登录后复制
    ,
    hash
    登录后复制
    ,
    signature
    登录后复制
    等),然后将这些参数通过API请求(比如一个GET请求)发送到
    verification.verify.api
    登录后复制
    这个后端路由。后端处理验证逻辑,然后返回JSON响应给前端。前端根据JSON响应来更新UI,比如显示“验证成功”或“验证失败”。

  4. 前端处理: 前端应用需要有一个专门的页面或组件来处理验证链接。当用户点击邮件中的链接,如果链接指向前端应用,前端需要:

    • 解析URL中的
      id
      登录后复制
      ,
      hash
      登录后复制
      ,
      signature
      登录后复制
      等参数。
    • 将这些参数发送到后端的
      verification.verify.api
      登录后复制
      端点。
    • 根据后端返回的JSON响应,显示验证结果。
    • 如果验证成功,可能需要提示用户登录或自动登录(如果前端可以处理Token)。

这种方式将验证逻辑完全放在后端API中,前端只负责触发和展示结果,保持了前后端分离的原则。

以上就是Laravel邮箱验证?验证功能如何添加?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号