# 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)