分析laravel8中的dingo與jwt鑒權(quán)

下面由laravel教程欄目給大家介紹laravel8中dingo與jwt鑒權(quán),希望對需要的朋友有所幫助!

1 什么是dingo

dingo api包是給laravel和lumen提供的Restful的工具包,它可以與jwt組件一起配合快速的完成用戶認(rèn)證,同時對于數(shù)據(jù)和運行過程中所產(chǎn)生的異常能夠捕獲到并且可以做出對應(yīng)的響應(yīng)。
主要功能:

  1. Router Version 路由版本管理
  2. http Exception 異常處理
  3. response transform 轉(zhuǎn)化響應(yīng)格式
1 安裝dingo

在laravel根目錄下通過composer進(jìn)行dingo擴(kuò)展包的安裝,具體命令如下:

composer require dingo/api

使用以下命令可以發(fā)布 API 的配置文件到 config 文件下:

php artisan vendor:publish --provider="DingoApiProviderLaravelServiceProvider"
2 配置dingo

關(guān)于dingo的api配置信,我們可以在.env文件中進(jìn)行配置

# dingo # API_SUBTYPE —— 項目的簡稱; API_SUBTYPE=lms # API_PREFIX —— 與 API_DOMAIN 二選一,路由的前綴,例如設(shè)置為 api API_PREFIX=api # 定義版本 API_VERSION=v1 # 是否開啟調(diào)試模式 API_DEBUG=true

關(guān)于dingo的詳細(xì)配置請查看相關(guān)文檔:https://learnku.com/docs/dingo-api/2.0.0/Configuration/1444

2 什么是JWT

jwt全稱JSON Web Tokens ,是一個非常輕巧的規(guī)范,這個規(guī)范允許我們使用jwt在用戶和服務(wù)器之間傳遞安全可靠的信息,他的主要使用場景為:認(rèn)證與數(shù)據(jù)交換

1 安裝JWT

在laravel根目錄下通過composer進(jìn)行jwt擴(kuò)展包的安裝,具體命令如下:

composer require tymon/jwt-auth

使用以下命令可以發(fā)布 API 的配置文件到 config 文件下:

php artisan vendor:publish --provider="TymonJWTAuthProvidersLaravelServiceProvider"
2 配置JWT

在.env文件中生成jwt加密秘鑰,具體命令如下:

php artisan jwt:secret

修改config/api.php配置

'auth' => [     'jwt' => 'DingoApiAuthProviderJWT', ],

修改config/auth.php配置

'defaults' => [         #注:這里修改改了默認(rèn)的配置,默認(rèn)是web         'guard' => 'api',         'passwords' => 'users',     ],     'guards' => [         'web' => [             'driver' => 'session',             'provider' => 'users',         ],          'api' => [             'driver' => 'jwt',             'provider' => 'users',             'hash' => false,         ],     ],

關(guān)于jwt的詳細(xì)配置請查看相關(guān)文檔:https://jwt-auth.readthedocs.io/en/develop/

3 相關(guān)代碼演示

創(chuàng)建RefreshToken中間件,用于令牌過期刷新

namespace AppHttpMiddleware;  use Closure; use IlluminateSupportFacadesAuth; use IlluminateHttpRequest; use SymfonyComponentHttpKernelExceptionUnauthorizedHttpException; use TymonJWTAuthExceptionsJWTException; use TymonJWTAuthExceptionsTokenExpiredException; use TymonJWTAuthHttpMiddlewareBaseMiddleware;  class RefreshToken extends BaseMiddleware {     /**      * Handle an incoming request.      *      * @param  IlluminateHttpRequest  $request      * @param  Closure  $next      * @return mixed      */     public function handle(Request $request, Closure $next)     {         // 檢查此次請求中是否帶有 token,如果沒有則拋出異常。         $this->checkForToken($request);          // 使用 try 包裹,以捕捉 token 過期所拋出的 TokenExpiredException  異常         try {             // 檢測用戶的登錄狀態(tài),如果正常則通過             if ($this->auth->parseToken()->authenticate()) {                 return $next($request);             }             throw new UnauthorizedHttpException('jwt-auth', '未登錄');         } catch (TokenExpiredException $exception) {             // 此處捕獲到了 token 過期所拋出的 TokenExpiredException 異常,我們在這里需要做的是刷新該用戶的 token 并將它添加到響應(yīng)頭中             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());             }         }          // 在響應(yīng)頭中返回新的 token         return $this->setAuthenticationHeader($next($request), $token);     } }

User模型需要實現(xiàn)兩個方法:getJWTIdentifier()和getJWTCustomClaims()

<?php  namespace AppModels;  use IlluminateContractsAuthMustVerifyEmail; use IlluminateFoundationAuthUser as Authenticatable; use IlluminateNotificationsNotifiable; use TymonJWTAuthContractsJWTSubject;  class User extends Authenticatable implements JWTSubject {     use Notifiable;      public $table = "user";      /**      * The attributes that are mass assignable.      *      * @var array      */     protected $fillable = [         'name', 'email', 'password','phone','status','create_time','addr_id'     ];      /**      * The attributes that should be hidden for arrays.      *      * @var array      */     protected $hidden = [         'password', 'remember_token',     ];      /**      * The attributes that should be cast to native types.      *      * @var array      */     protected $casts = [ //        'email_verified_at' => 'datetime',     ];      /**      * 指示是否自動維護(hù)時間戳      *      * @var bool      */     public $timestamps = false;      public function getJWTIdentifier()     {         return $this->getKey();     }     public function getJWTCustomClaims()     {         return [];     } } ?>

創(chuàng)建UserController用于鑒權(quán)等相關(guān)操作

<?php  namespace AppHttpControllersApiV1;  use AppHttpControllersController; use AppModelsUser; use DingoApiRoutingHelpers; use IlluminateHttpRequest;  class UserController extends Controller {     use Helpers;      public function __construct()     {        //除去token驗證的方法        $this->middleware('refresh.token', [             'except' => [                 'login',             ],         ]);     }       /**用戶登錄      * @param Request $request      * @return IlluminateHttpJsonResponse|void      */     public function login(Request $request)     {         $phone = $request->get('phone');          $user = User::where('phone', $phone)->first();  //        //attempt貌似無法驗證其他字段,如需用其他字段鑒權(quán)使用login() //        $credentials = request(['name','password']); //        if (!$token = auth()->attempt($credentials)) { //            return response()->json(['error' => 'Unauthorized'], 401); //        }          //只要是user實例就可以通過login鑒權(quán)         if (! $token = auth()->login($user)) {             return response()->json([                 "restful" => false,                 "message" => "賬號錯誤",             ]);         }          //獲取用戶信息         $user = $this->user();         $key = "user::info::".$user->id;         //Redis緩存用戶信息3600秒         Redis::set($key,serialize($user->original),"EX",3600);          return $this->respondWithToken($token);     }      /**獲取用戶      * Get the authenticated User.      *      * @return IlluminateHttpJsonResponse      */     public function user()     {         return response()->json(auth()->user());     }      /**用戶退出      * Log the user out (Invalidate the token).      *      * @return IlluminateHttpJsonResponse      */     public function logout()     {         auth()->logout();          return response()->json(["message" => "退出成功"]);     }      /**用戶登錄狀態(tài)刷新      * Refresh a token.      * @return IlluminateHttpJsonResponse      */     public function refresh()     {         return $this->respondWithToken(auth()->refresh());     }      /**返回值      * @param $token      * @return array      */     protected function respondWithToken($token)     {         return [             'access_token' => $token,             'token_type' => 'Bearer',             'expires_in' => auth()->factory()->getTTL() * 60,             'restful' => true         ];     } }

? 版權(quán)聲明
THE END
喜歡就支持一下吧
點贊12 分享