如何在Laravel API路由中实现用户注册后的邮箱验证功能
Laravel API 场景下邮箱验证实现方案
你的现有代码已经满足基础前置条件:User 模型已实现 MustVerifyEmail 接口,且数据表包含 email_verified_at 字段,只需按以下步骤调整即可:
1. 调整注册逻辑,触发验证邮件
在 AuthController 的 register 方法中,用户创建完成后添加发送验证邮件的逻辑,同时自定义验证链接跳转至你的 Angular 前端地址:
首先修改 app/Providers/AppServiceProvider.php 的 boot 方法,自定义验证链接生成规则:
<?php namespace App\Providers; use Illuminate\Auth\Notifications\VerifyEmail; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot() { VerifyEmail::createUrlUsing(function ($notifiable) { // 此处替换为你的Angular前端验证页面地址 $frontendUrl = env('FRONTEND_URL', 'http://localhost:4200') . '/verify-email'; // 生成Laravel签名URL参数 $verifyUrl = \URL::temporarySignedRoute( 'verification.verify', \Illuminate\Support\Facades\Config::get('auth.verification.expire', 60), [ 'id' => $notifiable->getKey(), 'hash' => sha1($notifiable->getEmailForVerification()), ] ); // 把签名参数拼到前端地址上 return $frontendUrl . '?' . parse_url($verifyUrl, PHP_URL_QUERY); }); } }
然后修改 AuthController 的 register 方法,添加发送邮件逻辑:
public function register(Request $request) { $validator = Validator::make($request->all(), [ 'name' => 'required|string|between:2,100', 'email' => 'required|string|email|max:100|unique:users', 'password' => 'required|string|confirmed|min:6', ]); if($validator->fails()){ return response()->json($validator->errors(), 422); } $user = User::create(array_merge( $validator->validated(), ['password' => bcrypt($request->password)] )); // 新增:发送邮箱验证邮件 $user->sendEmailVerificationNotification(); return response()->json([ 'message' => 'User successfully registered, please check your email for verification link', 'user' => $user ], 201); }
2. 新增邮箱验证相关接口
在 AuthController 中添加验证邮箱、重发验证邮件两个方法:
use Illuminate\Auth\Events\Verified; use Illuminate\Support\Facades\URL; // 验证邮箱 public function verify(Request $request) { $user = User::findOrFail($request->route('id')); if (!hash_equals((string) $request->route('hash'), sha1($user->getEmailForVerification()))) { return response()->json(['message' => 'Invalid verification link'], 403); } if ($user->hasVerifiedEmail()) { return response()->json(['message' => 'Email already verified'], 200); } if ($user->markEmailAsVerified()) { event(new Verified($user)); } return response()->json(['message' => 'Email verified successfully'], 200); } // 重发验证邮件 public function resend(Request $request) { if ($request->user()->hasVerifiedEmail()) { return response()->json(['message' => 'Email already verified'], 400); } $request->user()->sendEmailVerificationNotification(); return response()->json(['message' => 'Verification link sent']); }
3. 调整登录逻辑,增加邮箱验证校验
修改 login 方法,未验证邮箱的用户不允许登录:
public function login(Request $request){ $validator = Validator::make($request->all(), [ 'email' => 'required|email', 'password' => 'required|string|min:6', ]); if ($validator->fails()) { return response()->json($validator->errors(), 422); } // 新增:校验用户是否已验证邮箱 if (!auth()->validate($validator->validated())) { return response()->json(['error_message' => 'Invalid Credentials'], 401); } $user = auth()->getLastAttempted(); if (!$user->hasVerifiedEmail()) { return response()->json(['error_message' => 'Please verify your email first'], 403); } $token = auth()->login($user); return $this->createNewToken($token); }
4. 新增API路由
在 routes/api.php 中添加以下路由:
Route::get('/email/verify/{id}/{hash}', [AuthController::class, 'verify'])->middleware(['signed', 'throttle:6,1'])->name('verification.verify'); Route::post('/email/resend', [AuthController::class, 'resend'])->middleware(['auth:api', 'throttle:6,1'])->name('verification.send');
5. Angular前端适配
- 用户点击邮件内的验证链接会跳转至你的Angular验证页面,从页面URL中提取所有查询参数(expires、signature、id、hash),直接拼接在后端
/api/email/verify/{id}/{hash}接口后发起GET请求即可完成验证 - 若验证链接过期,可提供重发按钮,携带用户登录返回的JWT token调用
/api/email/resend接口重新发送验证邮件
注意:请提前在.env文件中配置好邮件发送相关参数,确保Laravel可以正常发送邮件。
内容的提问来源于stack exchange,提问作者user3653474
相关产品推荐
相关产品推荐

