使用REST API的Laravel 5.7电子邮件验证

14

如何为Rest API重新制作Laravel 5.7电子邮件验证?

还是从头开始做是否值得?


我实现了你的代码的一部分,并注意到你使用的是POST路由而不是GET?电子邮件将参数作为GET发送,如果这样的话会抛出未知方法异常。 - Austin Sweat
我不记得为什么这么做了。我根据响应重新制定了我的问题并更改了路由。谢谢! - Илья Зеленько
2个回答

37

这个例子对我有效。完整的项目代码在这里

1)重新设计了<强>VerificationController控制器

删除了重定向并使response()->json(...)响应。

<?php

namespace App\Http\Controllers\API\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\VerifiesEmails;
use Illuminate\Http\Request;
use Illuminate\Auth\Events\Verified;

class VerificationController extends Controller
{
    use VerifiesEmails;

    /**
     * Show the email verification notice.
     *
     */
    public function show()
    {
        //
    }

    /**
     * Mark the authenticated user's email address as verified.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function verify(Request $request)
    {
        // ->route('id') gets route user id and getKey() gets current user id() 
        // do not forget that you must send Authorization header to get the user from the request
        if ($request->route('id') == $request->user()->getKey() &&
            $request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        }

        return response()->json('Email verified!');
//        return redirect($this->redirectPath());
    }

    /**
     * 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()->json('User already have verified email!', 422);
//            return redirect($this->redirectPath());
        }

        $request->user()->sendEmailVerificationNotification();

        return response()->json('The notification has been resubmitted');
//        return back()->with('resent', true);
    }

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('signed')->only('verify');
        $this->middleware('throttle:6,1')->only('verify', 'resend');
    }
}

2) 添加通知:

我使得邮件中的链接指向我的前端,并包含了一个 temporarySignedRoute 链接以便请求。

use Illuminate\Auth\Notifications\VerifyEmail as VerifyEmailBase;

class VerifyEmail extends VerifyEmailBase
{
//    use Queueable;

    /**
     * Get the verification URL for the given notifiable.
     *
     * @param  mixed  $notifiable
     * @return string
     */
    protected function verificationUrl($notifiable)
    {
        $prefix = config('frontend.url') . config('frontend.email_verify_url');
        $temporarySignedURL = URL::temporarySignedRoute(
            'verification.verify', Carbon::now()->addMinutes(60), ['id' => $notifiable->getKey()]
        );

        // I use urlencode to pass a link to my frontend.
        return $prefix . urlencode($temporarySignedURL);
    }
}

3) 添加了配置文件 frontend.php

return [
    'url' => env('FRONTEND_URL', 'http://localhost:8080'),
    // path to my frontend page with query param queryURL(temporarySignedRoute URL)
    'email_verify_url' => env('FRONTEND_EMAIL_VERIFY_URL', '/verify-email?queryURL='),
];

4) 添加到用户模型:

use App\Notifications\VerifyEmail;

并且

/**
 * Send the email verification notification.
 *
 * @return void
 */
public function sendEmailVerificationNotification()
{
    $this->notify(new VerifyEmail); // my notification
}

5) 增加路由

Laravel 中使用以下路由:

// Email Verification Routes...
Route::get('email/verify', 'Auth\VerificationController@show')->name('verification.notice');
Route::get('email/verify/{id}', 'Auth\VerificationController@verify')->name('verification.verify');
Route::get('email/resend', 'Auth\VerificationController@resend')->name('verification.resend');

如果使用Auth::routes();,它们将被添加到应用程序中。
据我所知,对于Rest API来说,email/verify路由及其在控制器中的方法是不需要的。
6)在我的前端页面/verify-email(从frontend.php配置文件中),我向参数queryURL中包含的地址发出请求。
接收到的URL看起来像这样:
"http://localhost:8000/api/email/verify/6?expires=1537122891&signature=0e439ae2d511f4a04723a09f23d439ca96e96be54f7af322544fb76e3b39dd32"

我的请求(带有授权头):

await this.$get(queryURL) // typical get request

代码可以完美验证电子邮件,如果已经验证过,则可以捕获错误。同时,我可以成功地将消息重新发送到电子邮件中。
我是否犯了什么错误?如果您有任何改进意见,请告诉我,谢谢!

你好 ;) 我是一个新手API编程,我想知道,如果你有auth()->user(),它是否真的符合RESTful? - b00sted 'snail'
1
@nrkz 是的!但是你仍然需要使用 tymon/jwt-auth 包(例如),它集成了内置授权,所以 auth()->user() 起作用。 - Илья Зеленько
我成功地使用了你的代码。非常好。但是如何使用中间件来检查用户是否已验证? - Tudor-Radu Barbu
1
@ИльяЗеленько auth()->user()->getKey() = null 我需要将JWT令牌与接收到的URL一起发送,是吗? - Ahmed Aboud
1
@ИльяЗеленько,你如何在验证电子邮件时附加授权标头呢?因为它将成为邮件中的链接,我只能在其中附加查询参数,我不知道你是如何做到的? - Haritsinh Gohil

1

我尝试了Илья Зеленько的答案,但我必须修改VerificationController构造方法如下:

public function __construct()
{
    $this->middleware('auth')->except(['verify','resend']);
    $this->middleware('signed')->only('verify');
    $this->middleware('throttle:6,1')->only('verify', 'resend');
}

否则,Laravel需要身份验证才能访问验证和重新发送路由。

1
也许你应该完全删除 $this->middleware('auth')->except(['verify','resend']); 吗?因为只有两个方法:verifyresend。理论上,你还可以用 $this->middleware('throttle:6,1'); 替换 $this->middleware('throttle:6,1')->only('verify', 'resend'); - Илья Зеленько
@ИльяЗеленько 这种修改方式不会带来安全风险吗? - Farzan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接