Laravel Email Verification via Api

默认情况下,Laravel提供了一个web的邮箱验证路由,

Laravel 的 Auth\VerificationController 类包含了发送验证链接和验证 Email 的必要逻辑。通过将 verify 选项传给 Auth::routes 方法,就能为这个控制器注册所需要的路由:

Auth::routes(['verify' => true]);

没有api请求的。

先复制一下Auth文件夹内的VerificationController.php文件,到Api文件夹下,主要用来参考。

记得修改namespace

批注 2020-04-15 002823

然后在api.php文件中添加:

Route::get('email/resend', 'Api\VerificationController@resend')->name('verification.resend');

resend方法位于

VerifiesEmails trait内:

批注 2020-04-15 003225

然后在api.php文件中添加:

Route::get('email/verify/{id}/{hash}', 'Api\VerificationController@verify')->name('verification.verify');

该方法同样位于VerifiesEmails trait内:

批注 2020-04-15 003500

如果需要重写上述两个方法,在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接口:

批注 2020-04-15 005108

这个接口实现后才能使用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测试注册请求:

批注 2020-04-15 005334

注册成功,拿到token:

批注 2020-04-15 005414

然后设置token,发送请求至http://laravelauth.test/api/email/resend

批注 2020-04-15 005636

结果如下:

批注 2020-04-15 005715

打开Laravel.log文件可以看到发送了:

批注 2020-04-15 005833

拷贝这个链接,在postman中测试发送get请求至这个链接:

注:图上id已经是4了,因为我测试了几次发送再截的图。

批注 2020-04-15 012929

因为请求了第二次:

批注 2020-04-15 013020

我们添加一个api route测试验证的结果:

Route::get('verified-only', function (Request $request) {
    dd('You Are Verified!', $request->user()->name);
})->middleware('auth:api', 'verified');

批注 2020-04-15 013457

Postman中测试如下:

未登录的【无auth token的】

批注 2020-04-15 013554

登录了的【有token的】:

批注 2020-04-15 013637

附上最后的代码:

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);
    }
}

posted @ 2020-04-15 00:38  dzkjz  阅读(596)  评论(0编辑  收藏  举报