Laravel Email Verification via Api
默认情况下,Laravel提供了一个web的邮箱验证路由,
Laravel 的 Auth\VerificationController 类包含了发送验证链接和验证 Email 的必要逻辑。通过将 verify 选项传给 Auth::routes 方法,就能为这个控制器注册所需要的路由:
Auth::routes(['verify' => true]);
没有api请求的。
先复制一下Auth文件夹内的VerificationController.php文件,到Api文件夹下,主要用来参考。
记得修改namespace
然后在api.php文件中添加:
Route::get('email/resend', 'Api\VerificationController@resend')->name('verification.resend');
resend方法位于
VerifiesEmails trait内:
然后在api.php文件中添加:
Route::get('email/verify/{id}/{hash}', 'Api\VerificationController@verify')->name('verification.verify');
如果需要重写上述两个方法,在Api\VerificationController.php文件中添加:
/** * Mark the authenticated user's email address as verified. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */
public function verify(Request $request)
{
auth()->loginUsingId($request->route('id'));
if ($request->route('id') != $request->user()->getKey()) {
throw new AuthorizationException;
}
if ($request->user()->hasVerifiedEmail()) {
return \response(['message' => 'Already verified!']);
}
if ($request->user()->markEmailAsVerified()) {
event(new Verified($request->user()));
}
if ($response = $this->verified($request)) {
return $response;
}
return $request->wantsJson()
? new Response(['message' => 'Successfully verified!'], 204)
: redirect($this->redirectPath())->with('verified', true);
}
/** * Resend the email verification notification. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function resend(Request $request) { if ($request->user()->hasVerifiedEmail()) { return \response(['message' => 'Already verified!'], 204); } $request->user()->sendEmailVerificationNotification(); return \response(['message' => 'Email Sent!'], 200); }
因为是api请求,所以构造函数中修改
$this->middleware('auth');
为:
$this->middleware('auth:api')->only('resend');
记得将user模型类实现MustVerifyEmail接口:
这个接口实现后才能使用user发送验证邮件:
<?php namespace Illuminate\Contracts\Auth; interface MustVerifyEmail { /** * Determine if the user has verified their email address. * * @return bool */ public function hasVerifiedEmail(); /** * Mark the given user's email as verified. * * @return bool */ public function markEmailAsVerified(); /** * Send the email verification notification. * * @return void */ public function sendEmailVerificationNotification(); /** * Get the email address that should be used for verification. * * @return string */ public function getEmailForVerification(); }
接下来用Postman测试注册请求:
注册成功,拿到token:
然后设置token,发送请求至http://laravelauth.test/api/email/resend
结果如下:
打开Laravel.log文件可以看到发送了:
拷贝这个链接,在postman中测试发送get请求至这个链接:
注:图上id已经是4了,因为我测试了几次发送再截的图。
因为请求了第二次:
我们添加一个api route测试验证的结果:
Route::get('verified-only', function (Request $request) { dd('You Are Verified!', $request->user()->name); })->middleware('auth:api', 'verified');
Postman中测试如下:
未登录的【无auth token的】
登录了的【有token的】:
附上最后的代码:
User.php
<?php namespace App; use App\Notifications\testPasswordResetEmailNotification; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Passport\HasApiTokens; class User extends Authenticatable implements MustVerifyEmail { use Notifiable, HasApiTokens, SoftDeletes; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = [ 'name', 'email', 'password', ]; /** * The attributes that should be hidden for arrays. * * @var array */ protected $hidden = [ 'password', 'remember_token', ]; /** * The attributes that should be cast to native types. * * @var array */ protected $casts = [ 'email_verified_at' => 'datetime', ]; public function sendPasswordResetNotification($token) { $this->notify(New testPasswordResetEmailNotification($token)); } public function tasks() { return $this->hasMany(Task::class); } }
api.php
<?php use Illuminate\Http\Request; use Illuminate\Support\Facades\Route; /* |-------------------------------------------------------------------------- | API Routes |-------------------------------------------------------------------------- | | Here is where you can register API routes for your application. These | routes are loaded by the RouteServiceProvider within a group which | is assigned the "api" middleware group. Enjoy building your API! | */ Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); Route::middleware('auth:api')->get('/user', function (Request $request) { return $request->user(); }); //Route::get('verified-only', function (Request $request) { // dd('You Are Verified!', $request->user()->name); //})->middleware('auth:api', 'verified'); Route::post('login', 'Api\AuthController@login')->name('login.api'); Route::post('register', 'Api\AuthController@register')->name('register.api'); Route::middleware('auth:api')->get('logout', 'Api\AuthController@logout')->name('logout.api'); Route::post('/password/email', 'Api\ForgotPasswordController@sendResetLinkEmail'); Route::post('/password/reset', 'Api\ResetPasswordController@reset'); Route::apiResource('tasks', 'TaskController')->middleware('auth:api'); Route::get('email/resend', 'Api\VerificationController@resend')->name('verification.resend'); Route::get('email/verify/{id}/{hash}', 'Api\VerificationController@verify')->name('verification.verify');
VerificationController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Providers\RouteServiceProvider; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Auth\Events\Verified; use Illuminate\Foundation\Auth\VerifiesEmails; use Illuminate\Http\Request; use Illuminate\Http\Response; class VerificationController extends Controller { /* |-------------------------------------------------------------------------- | Email Verification Controller |-------------------------------------------------------------------------- | | This controller is responsible for handling email verification for any | user that recently registered with the application. Emails may also | be re-sent if the user didn't receive the original email message. | */ use VerifiesEmails; /** * Where to redirect users after verification. * * @var string */ protected $redirectTo = RouteServiceProvider::HOME; /** * Create a new controller instance. * * @return void */ public function __construct() { //修改為api $this->middleware('auth:api')->only('resend'); // 'signed'中間件 => \Illuminate\Routing\Middleware\ValidateSignature::class, $this->middleware('signed')->only('verify'); //1分鐘内最多只能發送6次請求 $this->middleware('throttle:6,1')->only('verify', 'resend'); } /** * Mark the authenticated user's email address as verified. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response * * @throws \Illuminate\Auth\Access\AuthorizationException */ public function verify(Request $request) { auth()->loginUsingId($request->route('id')); if ($request->route('id') != $request->user()->getKey()) { throw new AuthorizationException; } if ($request->user()->hasVerifiedEmail()) { return \response(['message' => 'Already verified!']); } if ($request->user()->markEmailAsVerified()) { event(new Verified($request->user())); } if ($response = $this->verified($request)) { return $response; } return \response(['message' => 'Successfully verified!']); } /** * Resend the email verification notification. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function resend(Request $request) { if ($request->user()->hasVerifiedEmail()) { return \response(['message' => 'Already verified!'], 204); } $request->user()->sendEmailVerificationNotification(); return \response(['message' => 'Email Sent!'], 200); } }