iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
0
Modern Web

RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄系列 第 13

Day 13. Knock knock! Who’s there? JSON Web Token (JWT)

  • 分享至 

  • xImage
  •  

Laravel 介紹的尾聲要再為各位介紹兩個安全機制讓我們的 API 使用上更為安全。今天帶來的是 JSON Web Token (JWT),明天則會說明 No Access-Control-Allow-Origin 這顆雷。

目前許多的網頁系統的登入機制是將登入者資訊存在 server session 作為辨識。但前後端分離之後 session 無法共用啊! 這樣 API 使用者不就無法確認身份;不然就是每次都要在 request 中帶入帳號、密碼進行驗證 ... 這未免太麻煩了吧,而且帳號、密碼被擷取的風險提高非常多!

因此 Auth0 提出一個 token 驗證方法。使用者在每次成功登入後,由 server 產出一組帶有登入者資訊的 token 給前端,之後每次使用 API 時,只要將這組 token 一同送到 server,並再執行 API 前先驗證使用者是否合法,藉這樣的機制達到保護後端資料。

前後端與 token 之間的關係如下圖所示:
https://ithelp.ithome.com.tw/upload/images/20190914/20112580Qpd6eYcFsJ.png

JWT 是由三組資料組成:

  • header: 存放演算法和 token 類型的資料
  • payload: 存放各種溝通資料,包括 token 到期時間,登入者資訊等聲明資料
  • signature: 驗證 token 真偽的簽章

接下來,將透過 tymon/jwt-auth 製作 JWT 並且實現登入登出:
01. 在 cmd 中執行下列指令安裝套件:

composer require tymon/jwt-auth 1.0.0-rc.4.1
  1. 執行下面紙令產出 JWT 的設定文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
  1. 執行下列指令,在 .env 中產生密鑰 (secret)
php artisan jwt:secret
  1. 開啟 User model,進行下列調整
// ...
use Tymon\JWTAuth\Contracts\JWTSubject;

                                // 實作 JWTSubject
class User extends Authenticatable implements JWTSubject
{
    // ...

    // 實作下列兩個方法
    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     *
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}
  1. 開啟 config/auth.php,對 defaultguardsproviders 三項進行調整:
    'defaults' => [
        'guard' => 'api', // web -> api
        'passwords' => 'users',
    ],

    'guards' => [
        'api' => [
            'driver' => 'jwt', // token -> jwt
            'provider' => 'users',
        ],
    ],

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class, // 確認路徑是否有需要調整
        ],
    ],
  1. 建立新的 middleware 處理 token 驗證。其中主要透過 Laravel helper auth()->user() 取得使用者,如果 token 有問題會回傳 null。
class JWTAuth
{
    public function handle($request, Closure $next, string $role)
    {
        // 驗證 token 並回傳 user
        $user = auth()->user();
        if ($user) {
            return $next($request);
        }

        // 拋出錯誤
        $errorResponseData = [ "message" => "Auth 警告: 沒有權限使用 API " ];
        throw new HttpResponseException(response()->json($responseData, 422));
    }
}
  1. 在 controller 登入方法中,使用 auth()->attempt() 產生 token。
class UserController extends Controller
{
    public function login(LoginRequest $request)
    {
        $loginData = $request->only(['email', 'password']);

        $token = auth()->attempt($loginData);

        // ...
    }
}
  1. 使用 auth()->logout() 完成登出方法
class UserController extends Controller
{
    public function logout()
    {
        auth()->logout();
        // ...
    }
}

今天很快的介紹套件的基礎功能 (更多細節可參考文件),透過運用 JWT 進行 API 使用者的身分驗證。至目前為止,更準確的說,在介紹完 route 之後就可以透過 Postman 連到寫好的 API,但真的以為 API 是可以通的嗎? 太天真惹 (欸 XD),明天沒有意外會是 Laravel 介紹的最後一天,再帶大家跳過一個常見的地雷 No Access-Control-Allow-Origin!


上一篇
Day 12. HiNet 有小天使,Laravel 有 Middleware !
下一篇
Day 14. 自己家的孩子自己打 - No Access-Control-Allow-Origin
系列文
RRR撞到不負責之 Laravel + Nuxt.js 踩坑全紀錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言