# laravel實作JWT登入驗證機制 ## 安裝JWT套件 JWT(Json Web Token)是一種對token進行編碼的方式,想了解詳情可到參考資料裡找到JWT的介紹。 首先在laravel專案底下打開命令提示字元,輸入以下指令安裝JWT套件: ``` composer require tymon/jwt-auth ``` 輸入以下指令,將JWT的資源檔複製到定的位置。 ``` php artisan vendor:publish ``` 輸入完後會出現一個列表,接著輸入JWT的編號,就可以安裝完成了。 ## 設定.env 打開專案中的.env,在最下方輸入以下程式碼: ``` php JWT_TTL=1440 //設定token時限為1440分鐘 ``` 打開命令提示字元,建立JWT的secret: ``` php artisan jwt:secret ``` 再打開.env檔,就會看到系統幫忙生成一個JWT的secret字串囉! ## 設定Model - app\models\User.php 打開User.php,新增getJWTIdentifier和getJWTCustomClaims這兩個方法,如下列所示: ``` php=1 <?php namespace App\Models; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable implements JWTSubject { use HasFactory, Notifiable; /** * The attributes that are mass assignable. * * @var array */ protected $fillable = ['name', 'email', 'password']; /** * 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', ]; public function getJWTIdentifier(){ return $this->getKey(); } public function getJWTCustomClaims(){ return []; } } ``` ## 設定auth.php - config\auth.php 將程式碼中guards=>api=>driver的部分修改成: ```php 'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'jwt', 'provider' => 'users', ], ], ``` ## 設定controller - app\Http\controllers\api\AuthController.php 請自行建立一個Controller,不會的可以參考之前的教學。 ```php=1 <?php namespace App\Http\Controllers\api; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Illuminate\Support\Str; use Illuminate\Support\Facades\Hash; use App\Models\MyUser; class AuthController extends Controller { public function __construct() { $this->middleware('auth:api')->except('login'); } public function login(Request $request) { $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]); } } ``` 程式碼中,__construct是指該類別建構時要執行的程式,這邊就是設定middleware,代表每當使用這個api的時候,都會經過auth的中繼站,請auth來幫我們驗證使用者是否有登入。以及排除login的方法,否則連login都要使用token,沒有登入哪裡來的token! 第20行的意思是取得request中的email和password參數,第22行是將這組帳號密碼進行驗證,如果驗證成功的話就回傳一組token,否則就回傳錯誤訊息。 :::warning 在登入的地方,laravel會自動將輸入的密碼做bcrypt加密,這邊要特別注意。 ::: ## 測試 打開Postman進行測試,在header的地方要加上下列數值: |key|value| |-|-| |Accept|application/json| |Authorization|Bearer +Your Token| 接著試著登入看看吧! :::warning 假設拿到的token為"12345",那麼Authorization的值則為"Bearer 12345" ::: ## 刷新token 刪除目前的token: ``` auth()-> invalidate(); ``` 用目前的token去取得一個新的token: ``` $token = auth()->fromUser(auth()->user()); ``` 這兩行程式碼可以寫在確認自己身分的API中,以本範例來說就是在AuthController的me方法裡面,先將傳進API中的token銷毀,在利用同一個使用者去產生一個新的API回傳回去。 ## 參考資料 [Laravel 與 JWT 搭配運用](https://hackmd.io/@8irD0FCGSQqckvMnLpAmzw/SkqRnxqIM?type=view) [Authenticating a Laravel API](https://www.youtube.com/watch?v=TTK8uQOjpT0&ab_channel=DigitalOcean) [Securing a Laravel API in 20 minutes with JWTs](https://www.youtube.com/watch?v=6eX9Pj-GhZs&ab_channel=AndrewSchmelyun) [How to Setup Jwt Token in laravel in Rest API](https://www.youtube.com/watch?v=VtAxYez4ZdQ&ab_channel=LaravelPackageTutorial) [[筆記] 透過 JWT 實作驗證機制](https://medium.com/%E9%BA%A5%E5%85%8B%E7%9A%84%E5%8D%8A%E8%B7%AF%E5%87%BA%E5%AE%B6%E7%AD%86%E8%A8%98/%E7%AD%86%E8%A8%98-%E9%80%8F%E9%81%8E-jwt-%E5%AF%A6%E4%BD%9C%E9%A9%97%E8%AD%89%E6%A9%9F%E5%88%B6-2e64d72594f8)