laravel 結合JWT開發API

    最近一直在忙公司小程序,還有微信的一些H5開發,固然做爲後端的我一直都只是寫寫簡單的邏輯。因爲以前一直都是混編開發,內心確實是累啊。因此也想能夠提高下組內的技術水平,同時也是爲了更好的分工,因而就想往先後端分離這種模式進行探索。php

    雖知道接觸一門新的東西,是要付出巨大的努力的。爲了可讓之後本身少走點彎路,在項目進度符合預期的同時,專門抽了時間針對API開發進行了碎片的學習。本篇文章借鑑了不少同行的事例代碼,同時也結合了本身的一點分析。但願各位道友能在其中有所感悟。前端

    談起API開發,我想第一個要解決的就是用戶的狀態問題吧,畢竟HTTP是屬於無狀態的協議,咱們在構建API的時候不能像普通的應用與系統開發同樣,直接把用戶的數據存放session而後再進行登陸的校驗。爲此有大神就想出了JWT相似的解決方案,經過token來對用戶的受權以及狀態進行一個感知。node

    在介紹 JWT 以前, 咱們首先介紹一下, 傳統的服務器端使用 session 對多用戶進行受權的方式. 固然在 session 以前還有 cookie 的方式來保存用戶的受權信息在客戶機(好比瀏覽器)上, 不過純 cookie 的方式過於不安全, 咱們就把 cookie 跟 session 一塊兒說.laravel

之因此須要受權機制, 是由於 http 的無狀態性(stateless).web

也就是說當一個用戶發送一次請求, 請求中附帶帳戶名和密碼登陸成功以後, 若是這個這個用戶再次發送一次請求, 服務器是不能知道這個用戶是已經登陸過的, 這個時候服務器就還須要用戶再次提供受權信息, 也就是用戶名和密碼.算法

若是客戶端能更少的把本身的身份受權信息在網絡上傳輸, 那麼客戶端就能更大程度上避免本身的身份信息被泄露.數據庫

而 session 和 token 都是爲了解決此問題出現的.json

session 原理概述

認證流程小程序

  1. 當用戶使用用戶名和密碼登陸以後, 服務器就會生成一個 session 文件, session 文件中保存着對這個用戶的受權信息, 這個文件能夠儲存在硬盤/內存/數據庫中.
  2. 同時還要生成一個對應這個 session 文件的 sessionid, 經過 sessionid 就可以找到這個 session 文件.
  3. 而後將 sessionid 發送給客戶端, 客戶端就將 sessionid 保存起來, 保存的方式有不少種, 目前大多狀況是經過 cookie 來保存 sessionid.
  4. 保存以後, 當客戶機之後再向服務器發送請求的時候, 請求攜帶上 sessionid, 這樣服務器收到 sessionid 以後, 本身就會在服務區上查找對應的 session 文件, 若是查找成功, 就會獲得該用戶的受權信息, 從而完成一次受權.

session 的出現解決了一部分的問題, 但隨着時間的推移和互聯網的發展, 一些缺陷也隨之暴露出來, 好比但不只限於如下幾點後端

  • 隨着用戶量的增長, 每一個用戶都須要在服務器上建立一個 session 文件, 這對服務器形成了壓力
  • 對於服務器壓力的分流問題, 若是一個用戶的 session 被存儲在某臺服務器上, 那麼當這個用戶訪問服務器時, 用戶就只能在這臺服務器上完成受權, 其餘的分流服務器沒法進行對這種請求進行分流
  • 一樣也是 session 存儲的問題, 當咱們在一臺服務器上成功登陸, 若是咱們想要另外的一臺別的域名的服務器也能讓用戶不登陸就能完成受權, 這個時候就會有不少麻煩

爲了解決此類問題, token 應運而生了.

Token 原理概述

認證流程

  1. 客戶端發送認證信息(通常就是用戶名/密碼), 向服務器發送請求
  2. 服務器驗證客戶端的認證信息, 驗證成功以後, 服務器向客戶端返回一個 加密的token(通常狀況下就是一個字符串)
  3. 客戶端存儲(cookie, session, app 中均可以存儲)這個 token, 在以後每次向服務器發送請求時, 都攜帶上這個 token
  4. 服務器驗證這個 token 的合法性, 只要驗證經過, 服務器就認爲該請求是一個合法的請求

JWT 概述

token 只是一種思路, 一種解決用戶受權問題的思考方式, 基於這種思路, 針對不一樣的場景能夠有不少種的實現. 而在衆多的實現中, JWT(JSON Web Token) 的實現最爲流行.

JWT 這個標準提供了一系列如何建立具體 token 的方法, 這些緣故方法和規範可讓咱們建立 token 的過程變得更加合理和效率.

好比, 傳統的作法中, 服務器會保存生成的token, 當客戶端發送來token時, 與服務器的進行比對, 可是 jwt 的不須要在服務器保存任何 token, 而是使用一套加密/解密算法 和 一個密鑰 來對用戶發來的token進行解密, 解密成功後就能夠獲得這個用戶的信息.

這樣的作法同時也增長了多服務器時的擴展性, 在傳統的 token 驗證中, 一旦用戶發來 token, 那麼必需要先找到存儲這個 token 的服務器是哪臺服務器, 而後由那一臺服務器進行驗證用戶身份. 而 jwt 的存在, 只要每一臺服務器都知道解密密鑰, 那麼每一臺服務器均可以擁有驗證用戶身份的能力.

這樣一來, 服務器就再也不保存任何用戶受權的信息了, 也就解決了 session 曾出現的問題.


簡單介紹完了 JWT 以後, 接下來咱們就簡單看一下在實際場景中 JWT 的應用.


Laravel

1. 使用 composer 安裝

# 建議使用1.0以上版本
composer require tymon/jwt-auth 1.*@rc
複製代碼

2. 進行一些配置

這裏指的注意的是,有些文檔會說要添加 Tymon\JWTAuth\Providers\LaravelServiceProvider::class,這隻在 Laravel 5.4 及如下版本是必要的,更新的 Laravel 版本無需添加。

還有一些文檔說要添加 Tymon\JWTAuth\Providers\JWTAuthServiceProvider 這是好久之前的 JWT 版本的(大概0.5.3 之前的版本)。

2.1 發佈配置文件

# 這條命令會在 config 下增長一個 jwt.php 的配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
複製代碼

2.2 生成加密密鑰

# 這條命令會在 .env 文件下生成一個加密密鑰,如:JWT_SECRET=foobar
php artisan jwt:secret
複製代碼

2.3 更新你的模型

若是你使用默認的 User 表來生成 token,你須要在該模型下增長一段代碼

<?php

namespace App;

use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable implements JWTSubject    # 這裏別忘了加
{
    use Notifiable;

    // Rest omitted for brevity

    /**
     * Get the identifier that will be stored in the subject claim of the JWT.
     * 獲取將存儲在JWT的中的標識符token。
     * @return mixed
     */
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     * 返回一個鍵值數組,其中包含要添加到JWT中的任何自定義聲明
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}
複製代碼

上面兩個方法,其實就是實現了JWTSubject藉口必須實現的方法。這個也是按照官方文檔進行配置便可。

2.4 註冊兩個 Facade

這兩個 Facade 並非必須的,可是使用它們會給你的代碼編寫帶來一點便利。

config/app.php

'aliases' => [
        ...
        // 添加如下兩行
        'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
        'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],
複製代碼

若是你不使用這兩個 Facade,你可使用輔助函數 auth()

auth() 是一個輔助函數,返回一個guard,暫時能夠當作 Auth Facade。

關於Auth Facade。建議你們參考這篇文章,我在學習JWT的時候也是看了好幾遍纔看懂的。

Laravel 輔助函數 auth 與 JWT 擴展詳解


2.5 修改 auth.php

config/auth.php

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'api' => [
        'driver' => 'jwt',      // 原來是 token 改爲jwt
        'provider' => 'users',
    ],
],
複製代碼

2.6 註冊一些路由

注意:在 Laravel 下,route/api.php 中的路由默認都有前綴 api

Route::group([

    'prefix' => 'auth'

], function ($router) {

    Route::post('login', 'AuthController@login');
    Route::post('logout', 'AuthController@logout');
    Route::post('refresh', 'AuthController@refresh');
    Route::post('me', 'AuthController@me');

});
複製代碼

2.7 建立 token 控制器

php artisan make:controller AuthController
複製代碼

AuthController

值得注意的是 Laravel 這要用 auth('api')

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;

class AuthController extends Controller
{
    /**
     * Get a JWT via given credentials.
     * 該方法用於生成token
     * @return \Illuminate\Http\JsonResponse
     */
    public function login()
    {
        $credentials = request(['email', 'password']);

        if (! $token = auth('api')->attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        return $this->respondWithToken($token);
    }

    /**
     * Get the authenticated User.
     * 該方法經過token獲取對應的用戶信息
     * @return \Illuminate\Http\JsonResponse
     */
    public function me()
    {
        return response()->json(auth('api')->user());
    }

    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout()
    {
        auth('api')->logout();

        return response()->json(['message' => 'Successfully logged out']);
    }

    /**
     * Refresh a token.
     * 刷新token,若是開啓黑名單,之前的token便會失效。
     * 值得注意的是用上面的getToken再獲取一次Token並不算作刷新,兩次得到的Token是並行的,即兩個均可用。
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh()
    {
        return $this->respondWithToken(auth('api')->refresh());
    }

    /**
     * Get the token array structure.
     *
     * @param  string $token
     * 該方法按照指定的格式返回輸出信息
     * @return \Illuminate\Http\JsonResponse
     */
    protected function respondWithToken($token)
    {
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth('api')->factory()->getTTL() * 60
        ]);
    }
}
複製代碼

JWT Token 詳解

1. token 的獲取、使用、刪除和刷新

  • 如下用 postman 演示,
  • Laravel 環境下寫在 api.php 中的路由默認有前綴 api

1.1 獲取 token


1.2 使用 token

有兩種使用方法:

  • 加到 url 中:?token=你的token
  • 加到 header 中,建議用這種,由於在 https 狀況下更安全:Authorization:Bearer 你的token


1.3 刪除 token


刪除 token 後,token就會失效,沒法再利用其獲取數據。


1.4 刷新 token



到此咱們就已經能夠成功地把JWT的開發例子演示完畢了,固然下面我會繼續的把一些經常使用的方法展現出來,另外也會附上JWT的一些數據結構的專門文章。

JWT實現原理

2. token 的建立

前面的 AuthController.php 中有兩行展示了這一種 token 的建立方法,即用用戶所給的帳號和密碼進行嘗試,密碼正確則用對應的 User 信息返回一個 token

token 的建立方法不止這一種,接下來介紹 token 的三種建立方法:

  • 基於帳密參數
  • 基於 users 模型返回的實例
  • 基於 users 模型中的用戶主鍵 id

a) 基於帳密參數

這就是剛剛說的哪種,貼出具體代碼。

// 使用輔助函數
$credentials = request(['email', 'password']); 
$token = auth('api')->attempt($credentials)

// 使用 Facade
$credentials = $request->only('email', 'password');
$token = JWTAuth::attempt($credentials);
複製代碼

b) 基於 users 模型返回的實例

// 使用輔助函數
$user = User::first();
$token = auth('api')->login($user);

// 使用 Facade
$user = User::first();
$token = JWTAuth::fromUser($credentials);
複製代碼

c) 基於 users 模型中的主鍵 id

// 使用輔助函數
$token = auth('api')->tokenById(1);
複製代碼

2.1 token 的解析

a) 解析 token 到對象

只有 Facade 須要這樣。

// 把請求發送過來的直接解析到對象
JWTAuth::parseToken();
複製代碼

b) 獲取 token 中的 user 信息

// 輔助函數
$user = auth()->user();

// Facade
$user = JWTAuth::parseToken()->authenticate();
複製代碼

c) 獲取 token

若是 token 被設置則會返回,不然會嘗試使用方法從請求中解析 token ,若是token未被設置或不能解析最終返回false。

// 輔助函數
$token = auth()->getToken();

// Facade
$token = JWTAuth::parseToken()->getToken();
複製代碼

d) 若是是前端

直接 base64 解碼 token 的前兩段便可以知道所需的信息。


3. 載荷的設置和獲取

a) 載荷設置

載荷信息會在 token 解碼時獲得,同時越大的數組會生成越長的 token ,因此不建議放太多的數據。同時由於載荷是用 Base64Url 編碼,因此至關於明文,所以絕對不能放密碼等敏感信息。

$customClaims = ['foo' => 'bar', 'baz' => 'bob'];

// 輔助函數
$token = auth()->claims($customClaims)->attempt($credentials);

// Facade - 1
$token = JWTAuth::claims($customClaims)->attempt($credentials);
複製代碼

b) 載荷解析

從請求中把載荷解析出來。能夠去看擴展源代碼,裏面還有不少的方法。

// 輔助函數
$exp = auth()->payload()->get('exp');
$json = auth()->payload()->toJson();
$array = auth()->payload()->jsonSerialize();
$sub = $array['sub'];

// Facade - 1
$payload = JWTAuth::parseToken()->getPayload();
$payload->get('sub'); // = 123
$payload['jti']; // = 'asfe4fq434asdf'
$payload('exp') // = 123456
$payload->toArray(); // = ['sub' => 123, 'exp' => 123456, 'jti' => 'asfe4fq434asdf'] etc

// Facade - 2
$exp = JWTAuth::parseToken()->getClaim('exp');
複製代碼

4. token 的三個時間

一個 token 通常來講有三個時間屬性,其配置都在 config/jwt.php 內。

有效時間

有效時間指的的是你得到 token 後,在多少時間內能夠憑這個 token 去獲取內容,逾時無效。

// 單位:分鐘
'ttl' => env('JWT_TTL', 60)
複製代碼

刷新時間

刷新時間指的是在這個時間內能夠憑舊 token 換取一個新 token。例如 token 有效時間爲 60 分鐘,刷新時間爲 20160 分鐘,在 60 分鐘內能夠經過這個 token 獲取新 token,可是超過 60 分鐘是不能夠的,而後你能夠一直循環獲取,直到總時間超過 20160 分鐘,不能再獲取。

// 單位:分鐘
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160)
複製代碼

寬限時間

寬限時間是爲了解決併發請求的問題,假如寬限時間爲 0s ,那麼在新舊 token 交接的時候,併發請求就會出錯,因此須要設定一個寬限時間,在寬限時間內,舊 token 仍然可以正常使用

// 寬限時間須要開啓黑名單(默認是開啓的),黑名單保證過時token不可再用,最好打開
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true)

// 設定寬限時間,單位:秒
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 60)
複製代碼

5.token 的刷新問題?

a) token 爲何要刷新嗎?

首先 Basic Auth 是一種最簡單的認證方法,可是因爲每次請求都帶用戶名和密碼,頻繁的傳輸確定不安全,因此纔有 cookiessession 的運用。若是 token 不刷新,那麼 token 就至關於上面的用戶名+密碼,只要獲取到了,就能夠一直盜用,所以 token 設置有效期並可以進行刷新是必要的。

b) token 有效期多久合適,刷新頻率多久合適?

有效期越長,風險性越高,有效性越短,刷新頻率越高,刷新就會存在刷新開銷,因此這須要綜合考慮。我我的通常考慮的範圍是:15min ~ 120min。

c) 有沒有必要每次都刷新 token ?

上面考慮的 15min ~ 120min,會存在一個問題,就是重放攻擊風險,防護這個風險,在 JWT 可用的方案是每次請求後都刷新一次 token ,但這樣又會存在一個新的問題:併發請求。一次併發請求是用的一個 token ,第一個完成的請求會致使後面的請求所有失敗。可用的解決方案是設置寬限時間,即一個 token 刷新後,舊 token 仍然短暫的可用。惋惜這樣並不能完美的解決重放攻擊,只是增大了不法者攻擊的成本。這個問題在 JWT 中並無很好的解決。

下面是可用的中間件,第一二個功能同樣,可是第二個不會拋出錯誤,第三四個功能同樣,沒什麼區別。

tymon\jwt-auth\src\Providers\AbstractServiceProvider.php

protected $middlewareAliases = [
    'jwt.auth' => Authenticate::class,
    'jwt.check' => Check::class,
    'jwt.refresh' => RefreshToken::class,
    'jwt.renew' => AuthenticateAndRenew::class,
];
複製代碼

5.1 token 的刷新總結

由於沒法徹底解決重放攻擊,因此在因重放攻擊會致使巨大安全問題和損失的地方,建議使用其餘安全認證措施。而平常 Api 使用建議以下設置:

有效時間:15min ~ 120min
刷新時間:7天 ~ 30天
寬限時間:60s
複製代碼


其餘經常使用方法附錄

1. JWT 的 兩個 Facade

1.1 JWTAuth

JWTAuth::parseToken()->方法() 通常均可以換成 auth()->方法()

token 生成

attempt

根據 user 帳密新建一個 token。

$credentials = $request->only('email', 'password');
$token = JWTAuth::attempt($credentials);
複製代碼

fromUser or fromSubject

根據 user 對象生成一個 token。後者是前者別名

$user = User::find(1);
$token = JWTAuth::fromUser($user);
複製代碼

token 控制

refresh

更新 token。

$newToken = JWTAuth::parseToken()->refresh();
複製代碼

invalidate

讓一個 token 無效。

JWTAuth::parseToken()->invalidate();
複製代碼

check

檢驗 token 的有效性。

if(JWTAuth::parseToken()->check()) {
    dd("token是有效的");
}
複製代碼

token 解析

authenticate or toUser or user

這三個效果是同樣的,toUserauthenticate 的別名,而 user 比前二者少一個 user id 的校驗,但並無什麼影響。

$user = JWTAuth::parseToken()->toUser();
複製代碼

parseToken

從 request 中解析 token 到對象中,以便進行下一步操做。

JWTAuth::parseToken();
複製代碼

getToken

從 request 中獲取token。

$token = JWTAuth::getToken();  // 這個不用 parseToken ,由於方法內部會自動執行一次
複製代碼

載荷控制

customClaims or claims

設置載荷的 customClaims 部分。後者是前者的別名。

$customClaims = ['sid' => $sid, 'code' => $code];
$credentials = $request->only('email', 'password');
$token = JWTAuth::customClaims($customClaims)->attempt($credentials);
複製代碼

getCustomClaims

獲取載荷的 customClaims 部分,返回一個數組。

$customClaims = JWTAuth::parseToken()->getCustomClaims()
複製代碼

getPayload or payload

獲取全部載荷,三個都是同樣的,最後一個通常用來檢驗 token 的有效性

$payload = JWTAuth::parseToken()->payload();

// then you can access the claims directly e.g.
$payload->get('sub'); // = 123
$payload['jti']; // = 'asfe4fq434asdf'
$payload('exp') // = 123456
$payload->toArray(); // = ['sub' => 123, 'exp' => 123456, 'jti' => 'asfe4fq434asdf'] etc
複製代碼

getClaim

獲取載荷中指定的一個元素

$sub = JWTAuth::parseToken()->getClaim('sub');
複製代碼

1.2 JWTGuard

這個 Facade 主要進行載荷的管理,返回一個載荷對象,而後能夠經過 JWTAuth 來對其生成一個 token

// 載荷的高度自定義
$payload = JWTFactory::sub(123)->aud('foo')->foo(['bar' => 'baz'])->make();
$token = JWTAuth::encode($payload);
複製代碼

$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
複製代碼

1.3 其餘一些用法

這裏用 auth 的寫法,由於 Laravel 有多個 guard,默認 guard 也不是 api ,因此須要寫成 auth('api') 不然,auth() 便可。

設置載荷

$token = auth('api')->claims(['foo' => 'bar'])->attempt($credentials);
複製代碼

顯示設置 token

$user = auth('api')->setToken('eyJhb...')->user();
複製代碼

顯示設置請求

$user = auth('api')->setRequest($request)->user();
複製代碼

重寫有效時間

$token = auth('api')->setTTL(7200)->attempt($credentials);
複製代碼

驗證帳密是否正確

$boolean = auth('api')->validate($credentials);
複製代碼


最後若是你想統一設置一下規則建議你仍是使用中間件吧,這樣你就能夠經過你的中間件去保護你須要驗證的路由與方法。文章貼出的是其餘大神寫的中間件,怎麼說好呢?各位道友本身好好去摸索摸索吧!

中間件代碼以下:

<?php

namespace App\Http\Middleware;

use Auth;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

// 注意,咱們要繼承的是 jwt 的 BaseMiddleware
class RefreshToken extends BaseMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     *
     * @throws \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException
     *
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // 檢查這次請求中是否帶有 token,若是沒有則拋出異常。 
        $this->checkForToken($request);

       // 使用 try 包裹,以捕捉 token 過時所拋出的 TokenExpiredException  異常
        try {
            // 檢測用戶的登陸狀態,若是正常則經過
            if ($this->auth->parseToken()->authenticate()) {
                return $next($request);
            }
            throw new UnauthorizedHttpException('jwt-auth', '未登陸');
        } catch (TokenExpiredException $exception) {
          // 此處捕獲到了 token 過時所拋出的 TokenExpiredException 異常,咱們在這裏須要作的是刷新該用戶的 token 並將它添加到響應頭中
            try {
                // 刷新用戶的 token
                $token = $this->auth->refresh();
               // 使用一次性登陸以保證這次請求的成功
                Auth::guard('api')->onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']);
            } catch (JWTException $exception) {
               // 若是捕獲到此異常,即表明 refresh 也過時了,用戶沒法刷新令牌,須要從新登陸。
                throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage());
            }
        }
        
        // 在響應頭中返回新的 token
        return $this->setAuthenticationHeader($next($request), $token);
    }
}複製代碼

更新異常處理的 Handler

因爲咱們構建的是 api 服務,因此咱們須要更新一下 app/Exceptions/Handler.php 中的 render

方法,自定義處理一些異常。

Handler.php

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;

class Handler extends ExceptionHandler
{
    ...

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Exception $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        // 參數驗證錯誤的異常,咱們須要返回 400 的 http code 和一句錯誤信息
        if ($exception instanceof ValidationException) {
            return response(['error' => array_first(array_collapse($exception->errors()))], 400);
        }
        // 用戶認證的異常,咱們須要返回 401 的 http code 和錯誤信息
        if ($exception instanceof UnauthorizedHttpException) {
            return response($exception->getMessage(), 401);
        }

        return parent::render($request, $exception);
    }
}複製代碼

至此,laravel的相關結合與學習暫告一段落!

相關文章
相關標籤/搜索