Jwt Auth(JSON Web Token 認證套件)

套件:tymon/jwt-auth

介紹

tymon/jwt-auth 是一個專為 Laravel 提供的 JWT(JSON Web Token)認證套件,主要用於實現無狀態的 API 認證機制,特別適用於需要 Token 驗證的應用程式,例如行動應用、單頁應用(SPA)或分散式系統。

主要特色包括:

  • 無狀態認證:每次 API 請求都攜帶 token,後端不需維護 session。
  • API 驗證最佳選擇:減少伺服器端的狀態依賴。
  • 整合簡易:提供方便的函式用來生成、驗證與刷新 token,支援 OAuth2 流程。

安裝與設定

composer require tymon/jwt-auth

# 發佈設定檔與生成金鑰
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
php artisan jwt:secret

設定 config/auth.php 的 guard:

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

使用 JWTAuth 生成與驗證 Token

當使用者登入後,後端會產生一個 JWT Token 並返回給前端,前端可儲存於 LocalStorage 或 Cookie,每次 API 請求附帶此 token。

use Tymon\JWTAuth\Facades\JWTAuth;

public function login(Request $request)
{
    $credentials = $request->only('email', 'password');

    if ($token = JWTAuth::attempt($credentials)) {
        return response()->json(['token' => $token]);
    }

    return response()->json(['error' => 'Unauthorized'], 401);
}

驗證 Token(中介層驗證)

使用 auth:api middleware 來驗證 API 請求是否附帶有效的 token:

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return response()->json($request->user());
});

登出(使 Token 失效)

JWT 是無狀態的,登出時需使 token 無效(加入黑名單):

public function logout()
{
    JWTAuth::invalidate(JWTAuth::getToken());
    return response()->json(['message' => 'Successfully logged out']);
}

完整範例:登入、驗證、登出

後端(Laravel)

// routes/api.php
use App\Http\Controllers\AuthController;

Route::post('login', [AuthController::class, 'login']);
Route::middleware('auth:api')->get('user', [AuthController::class, 'getUser']);
Route::middleware('auth:api')->post('logout', [AuthController::class, 'logout']);

// app/Http/Controllers/AuthController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;

class AuthController extends Controller
{
    public function login(Request $request)
    {
        $credentials = $request->only('email', 'password');

        if ($token = JWTAuth::attempt($credentials)) {
            return response()->json(['token' => $token]);
        }

        return response()->json(['error' => 'Unauthorized'], 401);
    }

    public function getUser(Request $request)
    {
        return response()->json($request->user());
    }

    public function logout()
    {
        JWTAuth::invalidate(JWTAuth::getToken());
        return response()->json(['message' => 'Successfully logged out']);
    }
}

前端(Vue + Axios)

import axios from 'axios';

axios.defaults.baseURL = 'http://your-laravel-api-url';
axios.defaults.headers.common['Authorization'] = `Bearer ${localStorage.getItem('token')}`;

async function login(email, password) {
    try {
        const response = await axios.post('/api/login', { email, password });
        localStorage.setItem('token', response.data.token);
    } catch (error) {
        console.error(error);
    }
}

async function getUser() {
    try {
        const response = await axios.get('/api/user');
        console.log(response.data);
    } catch (error) {
        console.error(error);
    }
}

async function logout() {
    try {
        await axios.post('/api/logout');
        localStorage.removeItem('token');
    } catch (error) {
        console.error(error);
    }
}

注意事項

  • Token 過期時間可在 config/jwt.php 中的 ttl 參數設定。
  • 建議將 Token 儲存在 httpOnly cookie 以增強安全性,避免 XSS 攻擊。

JWT Token 過期後的刷新機制

概念說明

刷新 token ≠ 延長原 token 的壽命
而是:棄用舊 token,產生新 token

Token 類型 儲存位置 用途 有效時間
Access Token LocalStorage / 記憶體 / Cookie 每次請求用於驗證 短(如 15 分鐘)
Refresh Token HttpOnly Cookie 用於換取新 Access Token 長(如 7~30 天)

優點

  • 舊 token 會被加入黑名單(blacklist),防止重用。
  • 前端可根據 401 自動嘗試 refresh。
  • 無縫續用使用者登入狀態。
  • 若過期過久或被刷新過,必須重新登入。

tymon/jwt-auth 的 Refresh 流程

  1. 使用者操作超過 token 過期時間。
  2. 發出 API 請求回傳 401。
  3. 前端使用 舊 token 呼叫 refresh API。
  4. 成功取得新 token,更新前端 token 儲存。
  5. 舊 token 自動加入黑名單。
use Tymon\JWTAuth\Facades\JWTAuth;

public function refresh()
{
    try {
        $newToken = JWTAuth::refresh(JWTAuth::getToken());
        return response()->json(['token' => $newToken]);
    } catch (\Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {
        return response()->json(['error' => 'Token 無效,請重新登入'], 401);
    }
}

若需要自訂 refresh 路由,請自行建立 Controller 並使用上述邏輯。


結語

  • JWT 是處理無狀態 API 認證的好幫手。
  • 若設計良好(包含過期與刷新),不僅能提升安全性,也能提升使用者體驗。
  • 建議搭配 token 黑名單與 refresh token 機制使用,避免永久有效 token 所產生的風險。

✅ 官方文件參考:https://jwt-auth.readthedocs.io/