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 之間的關係如下圖所示:
JWT 是由三組資料組成:
接下來,將透過 tymon/jwt-auth
製作 JWT 並且實現登入登出:
01. 在 cmd 中執行下列指令安裝套件:
composer require tymon/jwt-auth 1.0.0-rc.4.1
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
.env
中產生密鑰 (secret)php artisan jwt:secret
// ...
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 [];
}
}
config/auth.php
,對 default
、guards
和 providers
三項進行調整: 'defaults' => [
'guard' => 'api', // web -> api
'passwords' => 'users',
],
'guards' => [
'api' => [
'driver' => 'jwt', // token -> jwt
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class, // 確認路徑是否有需要調整
],
],
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));
}
}
auth()->attempt()
產生 token。class UserController extends Controller
{
public function login(LoginRequest $request)
{
$loginData = $request->only(['email', 'password']);
$token = auth()->attempt($loginData);
// ...
}
}
auth()->logout()
完成登出方法class UserController extends Controller
{
public function logout()
{
auth()->logout();
// ...
}
}
今天很快的介紹套件的基礎功能 (更多細節可參考文件),透過運用 JWT 進行 API 使用者的身分驗證。至目前為止,更準確的說,在介紹完 route 之後就可以透過 Postman 連到寫好的 API,但真的以為 API 是可以通的嗎? 太天真惹 (欸 XD),明天沒有意外會是 Laravel 介紹的最後一天,再帶大家跳過一個常見的地雷 No Access-Control-Allow-Origin
!