昨天簡單介紹了 JWT 認證機制,今天我們就來試試看!
這是一個用於 Laravel 框架的套件,專門設計來處理基於 JWT 的無狀態身份驗證。
更多相關資訊及安裝指令可以參考:JWTAuth 官方文件
JWT 使用一個密鑰來簽署 Token,所以先建立這個密鑰:
php artisan jwt:secret
這個指令會在你的 .env 檔案中加入一個 JWT_SECRET,這是用來保護和驗證 Token 的重要密鑰。
讓 User 模型實現 JWTSubject 介面,這樣可以告訴 JWT 如何處理使用者資料。
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
public function getJWTIdentifier()
{
return $this->getKey();
}
public function getJWTCustomClaims()
{
return [];
}
}
getJWTIdentifier()
負責告訴 JWT 這個 Token 屬於哪個使用者,通常是用「使用者的 id」。
getJWTCustomClaims()
允許你在 JWT 中加入額外的資訊,這樣可以在不查詢資料庫的情況下快速讀取一些常用的使用者屬性。
JWT 是用來取代 Laravel 預設的 Session 驗證,所以要修改 config/auth.php,將 API 的 guard 改為 jwt。
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
首先,建立一個 AuthController,也就是再指派一位專門處理這些功能的店長。
<?php
class AuthController extends Controller
{
// 註冊方法
public function register(Request $request)
{
// 使用 Validator 對請求資料進行驗證
$validator = Validator::make($request->all(), [
'name' => 'required|string|max:255', // 名字必填,字串類型,最大長度255
'email' => 'required|string|email|max:255|unique:users', // email必填,字串類型,格式為email,最大長度255,且在 users 表中必須唯一
'password' => 'required|string|min:6|confirmed', // 密碼必填,字串類型,最小長度為6,且需要確認
]);
// 如果驗證失敗,回傳錯誤訊息
if($validator->fails()){
return response()->json($validator->errors(), 400); // 回傳400狀態碼和錯誤訊息
}
// 創建新的使用者
$user = User::create([
'name' => $request->name, // 從請求中取得名字
'email' => $request->email, // 從請求中取得email
'password' => Hash::make($request->password), // 將密碼進行亂碼處理
]);
// 為新建立的使用者生成 JWT
$token = JWTAuth::fromUser($user);
// 回傳新使用者資料和 JWT,狀態碼為201
return response()->json(compact('user','token'), 201);
}
// 登入方法
public function login(Request $request)
{
// 只從請求中取得 email 和 password 欄位
$credentials = $request->only('email', 'password');
// 使用 JWTAuth 進行驗證
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401); // 驗證失敗,回傳401未授權
}
// 驗證成功,回傳 JWT
return response()->json(compact('token'));
}
// 登出方法
public function logout(Request $request)
{
$token = $request->bearerToken();
if (!$token) {
return response()->json(['error' => '需要提供token'], 401);
}
auth()->logout($token);
return response()->json(['message' => '您已登出成功!'], 200);
}
}
use App\Http\Controllers\AuthController;
Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:api');
可以使用 auth:api
中介層來保護需要身份驗證的路由。
例如:登入後需要取得會員資料,要再次驗證 token 成功!
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
輸入註冊資料,按下 Send 後:
出現一個 token 即為成功註冊!
選擇 Bearer Token:{{token}}
輸入 email 跟 密碼,按下 Send 後:
出現一個 token 即為成功登入!
選擇 Bearer Token:{{token}}
按下 Send 後:
{
"id": 2,
"name": "Test User2",
"email": "test2@example.com",
"email_verified_at": null,
"created_at": "2024-08-27 15:18",
"updated_at": "2024-08-27 15:18"
}
出現使用者資料即為成功!
選擇 Bearer Token:{{token}}
按下 Send 後:
出現設定好的訊息即為成功登出!