本文承接前文 [Day 27] Call API use JWT in Laravel: 簡介 和 安裝 ,將自制一個 Member model,應用 tymon/jwt-auth
做出 Login/ Logout 功能和應用 attempt()
時,需注意事項。設定上會與 jwt-auth 的 Quick start 稍有不同:
Member
model (implements JWTSubject
, add getJWTIdentifier()
, getJWTCustomClaims()
)<?php
namespace App\Models;
use Laravel\Sanctum\HasApiTokens;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Member extends Authenticatable implements JWTSubject
// class Member extends Authenticatable
{
use HasFactory, HasApiTokens, Notifiable;
protected $fillable = [
'name',
'email',
'password',
'mobile',
];
protected $hidden = [
'password',
'remember_token',
];
/**
* 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 [];
}
}
config/auth.php
)
config/auth.php
初始設定 'defaults' 設置 'guard' => 'web' ,这意味著預設的身份驗證 guard 是 Web guard,通常用於傳統的 Web 應用程序,而不是 API。routes/api.php
設定的 Route 需加上 middlewaremiddleware('auth:api')
->get('register' ..略),確保只有通過 API 身份驗證的用户才能訪問 /register
routes/api.php
的 Route:: 無需加上middleware('auth:api')
Route::
寫作:<?php
Route::middleware('auth:member')->apiResource('products', ProductController::class)->only('index', 'show');
auth.php
可以設定多個 guard 在 'guards' 內,現下 Call Api ,Route::
走 middleware('auth:member')
,本例 auth.php
設定:
<?php
return [
'defaults' => [
'guard' => 'api',
'passwords' => 'members',
],
'guards' => [
'member' => [
'driver' => 'jwt',
'provider' => 'members', // members table
],
],
'providers' => [
'members' => [
'driver' => 'eloquent',
'model' => App\Models\Member::class,
],
],
// ..略
];
php artisan make:controller AuthController
use Illuminate\Support\Facades\Auth;
Auth::
) 來存取 Laravel 的認證服務attempt()
,這個 attempt()
方法通常會用來處理來自網站「登入」表單的驗證Auth::attempt($credential)
),則應該產生使用者的 token
Auth::attempt($credential)
為 true)後,可透過 Auth::user()
取得使用者資訊Auth::attempt($credential)
為 false),可能的原因是註冊時,密碼未經加密,經過 attempt()
得到 false如果使用 web/session 方式,可以用密碼為明碼吧?!
<?php
public function login(Request $request)
{
$credential = $this->validate($request, [
'mobile' => ['required', 'email', 'max:255'],
'password' => ['required', 'alpha_num', 'min:4', 'max:8'],
]);
// 認證成功會給予token、認證不成功會給你false
$token = Auth::attempt($credential);
// 取得目前登入的使用者資訊
$user = Auth::user();
abort_if(!$token, Response::HTTP_BAD_REQUEST, '帳號密碼錯誤');
return response(['data' => $token, 'user' => $user]);
}
login()
的 Auth::attempt($credential)
,也就是不管是 api/jwt 或 web/session 加密後的密碼,才能通過 attempt()
,若使用明碼通過 attempt()
則會得到 false
attempt()
將上述 $credential
陣列中的值,用來在資料庫資料表中尋找使用者。因此,在上方的範例中,使用者會依照 mobile 欄位中的值來取得。若找到該使用者,則會將資料庫中儲存的密碼雜湊跟陣列中的 password 值進行比對。
Logout 的前提必須是 "登入" 狀態,當使用者在 "登入" 狀態下,會有一組 JWT token,清除使用者的認證狀態(JWT 工具產生的 token),即為使使用者登出
middleware('auth:member')
確認是 "登入" 狀態,才能允許他們繼續訪問 Route::post('logout', ..略)
127.0.0.1:8083/v1/members/logout
<?php
Route::middleware(['auth:member'])->group(function () {
Route::post('/members/logout', [AuthController::class, 'logout']);
});
Auth::logout()
,它會清除使用者的認證狀態(JWT 工具產生的 token),促使 使用者登出return response()->noContent()
會回傳一個 HTTP 狀態碼為 204 No Content 的回應給客戶端,代表成功執行但不需要回傳任何資料
<?php
public function logout()
{
// 清除使用者的認證狀態(JWT 工具產生的 token)
Auth::logout();
return response()->noContent();
}
call api 的 JWT 類似金手指的概念,它提供 call api 所需的認證,經由設定 config/auth.php
和 Member model implements JWTSubject
,在 AuthController
內,用 Auth::
來使用 JWT 的功能,例如:
Auth::attempt($credential)
, Auth::logout()
, Auth::user()
等功能1 [Day 27] Call API use JWT in Laravel: 簡介 和 安裝
2 Laravel #Manually Authenticating Users