Laravel Api實現JWT Token認證
在開發Api時,處理客戶端請求之前,需要對使用者進行身份認證,Laravel框架預設為我們提供了一套使用者認證體系,在進行web開發時,幾乎不用新增修改任何程式碼,可直接使用,但在進行api開發時,需要我們自己去實現,並且Laravel框架預設提供的身份認證不是jwt的,需要在資料庫中增加api_token欄位,記錄使用者認證token並進行身份校驗,如果需要使用jwt,無需新增欄位,需要藉助三方庫來實現。
Token認證原理
-
客戶端傳送認證資訊 (一般就是使用者名稱 / 密碼), 向伺服器傳送請求
-
伺服器驗證客戶端的認證資訊,驗證成功之後,伺服器向客戶端返回一個 加密的 token (一般情況下就是一個字串)
-
客戶端儲存 (cookie, session, app 中都可以儲存) 這個 token, 在之後每次向伺服器傳送請求時,都攜帶上這個 token
-
伺服器驗證這個 token 的合法性,只要驗證通過,伺服器就認為該請求是一個合法的請求
JWT概述
token 只是一種思路,一種解決使用者授權問題的思考方式,基於這種思路,針對不同的場景可以有很多種的實現。而在眾多的實現中,JWT (JSON Web Token) 的實現最為流行.
JWT 這個標準提供了一系列如何建立具體 token 的方法,這些緣故方法和規範可以讓我們建立 token 的過程變得更加合理和效率.
比如,傳統的做法中,伺服器會儲存生成的 token, 當客戶端傳送來 token 時,與伺服器的進行比對,但是 jwt 的不需要在伺服器儲存任何 token, 而是使用一套加密 / 解密演算法 和 一個金鑰 來對使用者發來的 token 進行解密,解密成功後就可以得到這個使用者的資訊.
這樣的做法同時也增加了多伺服器時的擴充套件性,在傳統的 token 驗證中,一旦使用者發來 token, 那麼必須要先找到儲存這個 token 的伺服器是哪臺伺服器,然後由那一臺伺服器進行驗證使用者身份。而 jwt 的存在,只要每一臺伺服器都知道解密金鑰,那麼每一臺伺服器都可以擁有驗證使用者身份的能力.
這樣一來,伺服器就不再儲存任何使用者授權的資訊了,也就解決了 session 曾出現的問題.
實現方法
1.安裝jwt-auth
composer require tymon/jwt-auth:dev-develop
參考文件:
https://github.com/tymondesigns/jwt-auth/wiki/Installation
2.在config/app.php
的providers
配置項中註冊服務提供者
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
3.生成配置檔案
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此命令會在config
目錄下生成jwt.php
配置檔案
4.生成金鑰
php artisan jwt:secret
此命令會在你的.env
檔案中新增一行JWT_SECRET=secret
5.建立模型
php artisan make:model Models/User
程式碼:
<?php namespace App\Models; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { protected $fillable = ['name', 'password']; protected $hidden = ['password', 'remember_token']; // public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
6.修改配置檔案auth.php
'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', 'hash' => false, ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class ], ],
7.實現登入註冊返回token
php artisan make:controller Api/UserController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\Member; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class PassportController extends Controller { public function __construct() { $this->middleware('auth:api', ['except' => ['register', 'login']]); } /** * 使用者註冊 */ public function register(Request $request) { // jwt token $credentials = [ 'name' => $request->name, 'password' => Hash::make($request->password) ]; $user = User::create($credentials); if($user){ $token = = JWTAuth::fromUser($user); return $this->responseWithToken($token); } } /** * 使用者登入 */ public function login(Request $request) { // todo 使用者登入邏輯 // jwt token $credentials = $request->only('name', 'password'); if (!$token = auth()->attempt($credentials)) { return response()->json(['result'=>'failed']); } return $this->responseWithToken($token); } /** * 重新整理token */ public function refresh() { return $this->responseWithToken(auth()->refresh()); } /** * 退出登入 */ public function logout(Request $request) { auth()->logout(); } /** * 響應 */ private function responseWithToken(string $token) { $response = [ 'access_token' => $token, 'token_type' => 'Bearer', 'expires_in' => auth()->factory()->getTTL() * 60 ]; return response()->json($response); } }
原文地址:https://www.stephen520.cn/blog/10255