---
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 身分驗證的機制就完成了