參考鏈接
Laravel 的 API 認證系統(tǒng) Passport 三部曲(一、passport安裝+配置)
Laravel 的 API 認證系統(tǒng) Passport
引言
- 在使用前要先了解Auth2.0的使用方式和原理Laravel 的用戶認證系統(tǒng)
- passport是專門做api令牌授權的工具,這里有個問題是他不像auth一樣可以定義多個guard來區(qū)分不同平臺走不同的auth認證模塊,他默認只走guard=api這個api認證模塊。
密碼授權令牌的獲取
-
請求令牌
創(chuàng)建密碼授權的客戶端后,就可以通過向用戶的電子郵件地址和密碼向 /oauth/token 路由發(fā)出 POST 請求來獲取訪問令牌。而該路由已經(jīng)由 Passport::routes 方法注冊,因此不需要手動定義它。如果請求成功,會在服務端返回的 JSON 響應中收到一個 access_token 和 refresh_token:$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '', ], ]); return json_decode((string) $response->getBody(), true);
私人訪問令牌
在你的應用程序發(fā)布個人訪問令牌之前,你需要在 passport:client 命令后帶上 --personal 參數(shù)來創(chuàng)建對應的客戶端。如果你已經(jīng)運行了 passport:install 命令,則無需再運行此命令:
php artisan passport:client --personal
創(chuàng)建個人訪問客戶端后,你可以使用 User 模型實例上的 createToken 方法來為給定用戶發(fā)布令牌。
createToken 方法接受令牌的名稱作為其第一個參數(shù)和可選的 作用域 數(shù)組作為其第二個參數(shù):
$user = App\User::find(1);
// Creating a token without scopes...
$token = $user->createToken('Token Name')->accessToken;
// Creating a token with scopes...
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
注意: 由于passport默認只可以走一個guard認證,當多平臺的時候,可以使用auth2.0來輔助操作,首先使用Auth2.0驗證該平臺對應的guard(當然,驅(qū)動使用session))下其賬號密碼是否正確,驗證通過之后再獲取該用戶實例并給予私人訪問令牌,這樣就做到了不同平臺的令牌生成)
驗證令牌
-
通過中間件
Passport 包含一個 驗證保護機制 可以驗證請求中傳入的訪問令牌。配置 api 的看守器使用 passport 驅(qū)動程序后,只需要在需要有效訪問令牌的任何路由上指定 auth:api 中間件:
Route::get('/user', function () { // })->middleware('auth:api'); -
我們實現(xiàn)方式
由于passport只可以走api一個guard驗證,也就是只可以走一個用戶授權表,這里我們多平臺多登陸授權表則只用上面的驗證登陸肯定就不對了,如上所說我們結合auth2.0來進行分平臺進行驗證。
- 首先創(chuàng)建一個AuthApi中間鍵
- 在/app/Http/Kernel.php中注冊AuthApi中間鍵
eg:
public function handle($request, Closure $next, $guard = null) { if (empty(Auth::guard($guard)->user())) { return response()->json(["message" => "Unauthenticated."], 401); } return $next($request); }protected $routeMiddleware = [
'apiAuth' => ApiAuth::class,
......
];- 使用的時候比如要使用guard=home的驗證令牌,則中間件為“apiAuth:home”即可
注銷登錄、定期檢查過期token,銷毀舊的token
-
注銷登錄
eg:
/** * 登出程序操作. * * @return \Illuminate\Http\Response */ public function logout() { $user = $this->guard()->user(); if (empty($user)) { return $this->sendError('暫未登錄', ['暫未登錄'], 403); } // 獲取當前登陸用戶的access_token的id $accessToken = $user->access_token; // 找到這條access_token并且將其刪除 $token = Token::find($accessToken); if (empty($token)) { return $this->sendError('暫無有效令牌', ['暫無有效令牌'], 403); } if (!empty($token->delete())) { return $this->sendResponse([], '退出成功!'); } else { return $this->sendError('退出失敗', ['退出失敗'], 500); } } -
定期檢查過期token(官方文檔沒給,個人做的優(yōu)化)
-
創(chuàng)建token生成事件的監(jiān)聽器來處理該用戶當前客戶端下的所有失效的token
在“/app/Providers/EventServiceProvider.php”中的“$listen”數(shù)組中添加
// 生成token,檢查失效的進行刪除 'Laravel\Passport\Events\AccessTokenCreated' => [ 'App\Listeners\RevokeOldTokens', ],終端執(zhí)行:
php artisan event:generate提示:"Events and listeners generated successfully!"代表創(chuàng)建成功了
-
執(zhí)行刪除失效token操作
在 'App\Listeners\RevokeOldTokens'的handle方法中執(zhí)行刪除失效token操作
Token::where('id', '!=', $event->tokenId) ->where('user_id', $event->userId) ->where('client_id', $event->clientId) ->where('expires_at', '<', Carbon::now()) ->orWhere('revoked', true) ->delete();
-