尤川豪   ·  3週前
Exp. 1,763  ·  229 貼文  ·  160 留言

Laravel 預設的 MustVerifyEmail 是如何實做?

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail

Q1: 沒有存資料進 database,如何透過 email 驗證 token?

追蹤原始碼看到

    public function verify(Request $request)
    {
        if ($request->route('id') != $request->user()->getKey()) {
            throw new AuthorizationException;
        }

        if ($request->user()->hasVerifiedEmail()) {
            return redirect($this->redirectPath());
        }

        if ($request->user()->markEmailAsVerified()) {
            event(new Verified($request->user()));
        }

        return redirect($this->redirectPath())->with('verified', true);
    }

追蹤發現

Signed URLs

https://laravel.com/docs/5.8/urls#signed-urls

超帥的,這功能很酷!

多追蹤之後發現

public function signedRoute($name, $parameters = [], $expiration = null, $absolute = true)
{
    $parameters = $this->formatParameters($parameters);

    if ($expiration) {
        $parameters = $parameters + ['expires' => $this->availableAt($expiration)];
    }

    ksort($parameters);

    $key = call_user_func($this->keyResolver);

    return $this->route($name, $parameters + [
        'signature' => hash_hmac('sha256', $this->route($name, $parameters, $absolute), $key),
    ], $absolute);
}
public function hasValidSignature(Request $request, $absolute = true)
{
    $url = $absolute ? $request->url() : '/'.$request->path();

    $original = rtrim($url.'?'.Arr::query(
        Arr::except($request->query(), 'signature')
    ), '?');

    $expires = $request->query('expires');

    $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));

    return  hash_equals($signature, (string) $request->query('signature', '')) &&
           ! ($expires && Carbon::now()->getTimestamp() > $expires);
}

似乎沒碰到 database 也沒碰到 storage

沒存任何東西 就是一串加密與比較的程序

Q2: implements 介面,但沒有 use Traits,為何會有功能?

我們的 User class 是

<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{

而去繼承的母類別是

<?php

namespace Illuminate\Foundation\Auth;

use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;

class User extends Model implements
    AuthenticatableContract,
    AuthorizableContract,
    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

所以其實 code 是在 MustVerifyEmail trait 裡面,跟介面無關。

也就是 use Trait 是在母類別裡面啦。

  分享   共 73 次點閱
共有 0 則留言
您的留言
  贊助本站開發,解鎖進階教材
尤川豪
Exp. 1,763  ·  229 貼文  ·  160 留言

關於作者

Devs.tw 作者,喜歡分享&建造新東西的工程師。

歡迎在 Facebook 追蹤我!不定期分享有趣技術文章!

  查看個人檔案