--- tags: PHP / Laravel / Lumen --- # Laravel 與 JWT 搭配運用 ## Official Documentation [https://jwt-auth.readthedocs.io/en/develop/](https://jwt-auth.readthedocs.io/en/develop/) ## JWT ? 在Laravel中,web端預設是利用session識別登入者身分合法與否,而API則可利用「**JWT** (**Json Web Tokens**)」進行身分驗證,它本身是個JSON格式的輕量級規範,有別於**SAML** (**Security Assertion Markup Language**) 較為複雜的XML格式。 ## API Access Token ? 即造訪後端的憑證,首先使用者會在前端進行登入的動作,若身分核對成功後,就會發一組 Token 給前端,此時就可以利用Bearer作為驗證方案,將這組憑證夾帶在Header,造訪需要權限的API,讓後端知道你的身分是合法的。一般而言 Token 是具有時效性的,以 JWT 為例,時效預設為60分鐘,時效一過或者自行登出,則該 Token 失效,必須重新取得 Token。 ## Practice #### 利用composer引入jwt-auth: ```composer require tymon/jwt-auth:dev-develop``` #### config\app.php 於 「providers」新增 (Laravel 5.4 or below): ```php 'providers' => [ ... /* * Package Service Providers... */ Tymon\JWTAuth\Providers\LaravelServiceProvider::class, ], ... ``` #### 依據底層套件,發行 jwt.php 設定檔 (位於config資料夾): ```php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"``` #### 在「.env」產生JWT憑證,若憑證為空值,則被視為不合法身分 ```php artisan jwt:secret``` #### User model 引入 JWTSubject,宣告User model為JWTSubject介面,並加入下列2個方法: ```php <?php namespace App\Entities; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Notifications\Notifiable; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { use Notifiable; ... (略) /** * 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 : ```php 'defaults' => [ 'guard' => 'api', 'passwords' => 'users', ], ... 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], ``` #### routes\api.php創建路由: ```php Route::group(['prefix' => 'auth'], function () { Route::get('/', 'AuthController@me'); Route::post('login', 'AuthController@login'); Route::post('logout', 'AuthController@logout'); }); ``` #### 創建AuthController: ```php artisan make:controller AuthController``` #### app\Http\Controllers\AuthController.php ```php <?php namespace App\Http\Controllers; class AuthController extends Controller { public function __construct() { $this->middleware('auth:api')->except('login'); } public function login() { $credentials = request(['email', 'password']); if (! $token = auth()->attempt($credentials)) { return response()->json(['status' => 1, 'message' => 'invalid credentials'], 401); } return response()->json(['status' => 0, 'token' => $token]); } public function me() { return response()->json(auth()->user()); } public function logout() { auth()->logout(); return response()->json(['status' => 0]); } } ``` ## Running with postman API參數對照表 | URI | description | HTTP Method | Header | | -------- | -------- | -------- | -------- | | api/auth | 取得user資訊 | GET | Authorization: bearer **Token** <br >Accept: application/json | | api/auth/login | 登入 | POST | | | api/auth/logout | 登出 | POST | Authorization: bearer **Token** <br >Accept: application/json | 打開postman後,使用「取得user資訊」的API,若不夾帶token、token失效或者使用非法token,就會收到如下圖的回應,且HTTP Status Code 為401 ![](https://i.imgur.com/49VlIwK.png) 為何我們會收到401的狀態碼呢?因為這支 API 被宣告使用「auth:api」的中介層,倘若你身分是不合法的,就會被中介層拒於門外。這時我們就透過「登入」,取得合法的Token,並再次取得user資訊,結果就會如下 ![](https://i.imgur.com/OgwNqXG.png) 就這樣,利用 JWT 進行 API 身分驗證的機制就完成了