6

使用 JWT 身份驗證實作 Laravel REST API

 2 years ago
source link: https://calvertyang.github.io/2020/06/16/implement-laravel-rest-api-using-jwt-authentication/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Laravel 預設提供了 3 種身份驗證方式,分別為 authauth.basicguest,並透過 middleware 提供我們使用。

不過通常我們在提供 API 時會採用 JWT 來實作所需要的身份驗證功能,在 Laravel 中我們通常會使用 tymon/jwt-auth 來實作 JWT,以下就讓我們一起來實作吧。

本文實作時採用的是 Laravel 7.15.0tymon/jwt-auth 1.0.0

透過 composer 安裝套件

執行以下指令來安裝最新版本:

composer require tymon/jwt-auth

加入服務提供者(Service Provider)及別名(Alias)

開啟 config/app.php 設定檔,將其加到 providersaliases 陣列中:

config/app.php
'providers' => [ /* * Package Service Providers... */ Tymon\JWTAuth\Providers\LaravelServiceProvider::class, ], 'aliases' => [ ... 'JWTAuth' => Tymon\JWTAuth\Facades\JWTAuth::class, 'JWTFactory' => Tymon\JWTAuth\Facades\JWTFactory::class, ],

加入 middleware

jwt-auth 提供了幾個 middleware,將其加到 app\Http\Kernel.php 中的 $routeMiddleware 陣列中,之後便可在路由中使用 middleware。

app\Http\Kernel.php
/** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ ... 'jwt.auth' => Tymon\JWTAuth\Middleware\Authenticate::class, 'jwt.check' => Tymon\JWTAuth\Middleware\Check::class, 'jwt.refresh' => Tymon\JWTAuth\Middleware\RefreshToken::class, 'jwt.renew' => Tymon\JWTAuth\Middleware\AuthenticateAndRenew::class, ];

建立設定檔

執行以下指令來建立套件設定檔:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

執行以下指令來產生一組用於對 token 進行簽章的密鑰,具體的簽章方式取決於你選擇的演算法:

php artisan jwt:secret

執行後會在你的 .env 檔案中加上如 JWT_SECRET=foobar 之類的內容。

更新 User model

首先,你需要在 User model 實作 Tymon\JWTAuth\Contracts\JWTSubject 契約,它要求你實作 getJWTIdentifier()getJWTCustomClaims() 方法。

以下的範例是實作後大致上的樣子。當然,在必要時你可以進行任何修改,以滿足自己的需求。

app/User.php
<?php namespace App; use Illuminate\Contracts\Auth\MustVerifyEmail; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Tymon\JWTAuth\Contracts\JWTSubject; class User extends Authenticatable implements JWTSubject { use 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', ]; /** * Get the identifier that will be stored in the subject claim of the JWT. * * @return mixed */ public function getJWTIdentifier() { return $this->getKey(); } /** * Return a key value array, containing any custom claims to be added to the JWT. * * @return array */ public function getJWTCustomClaims() { return []; } }

設定 Auth guard

config/auth.php 檔案中,你需要進行一些修改,以便設定 Laravel 使用 JWT guard 來增強你的應用程式驗證功能。

以下是我們對檔案所做的變更:

config/auth.php
return [ ... 'guards' => [ ... 'api' => [ 'driver' => 'jwt', 'provider' => 'users', 'hash' => false, ], ], ... ];

在這裡,我們告訴 api guard 使用 jwt driver。

現在,我們可以使用 Laravel 內建的驗證系統,並透過 jwt-auth 在背後工作!

讓我們在 routes/api.php 中加入一些路由及 middleware,如下所示:

routes/api.php
Route::post('login', 'AuthController@login'); Route::group(['middleware' => 'jwt.auth',], function () { Route::post('logout', 'AuthController@logout'); Route::post('refresh', 'AuthController@refresh'); Route::get('me', 'AuthController@me'); });

建立 Auth Controller

你可以手動或透過 artisan 指令建立 AuthController

php artisan make:controller AuthController

建立完畢後,加入以下內容:

app/Http/Controllers/AuthController.php
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; class AuthController extends Controller { /** * Get a JWT token via given credentials. * * @param \Illuminate\Http\Request $request * * @return \Illuminate\Http\JsonResponse */ public function login(Request $request) { $credentials = $request->only('email', 'password'); if ($token = $this->guard()->attempt($credentials)) { return $this->respondWithToken($token); } return response()->json(['error' => 'Unauthorized'], 401); } /** * Get the authenticated User * * @return \Illuminate\Http\JsonResponse */ public function me() { return response()->json($this->guard()->user()); } /** * Log the user out (Invalidate the token). * * @return \Illuminate\Http\JsonResponse */ public function logout() { auth()->logout(); return response()->json(['message' => 'Successfully logged out']); } /** * Refresh a token. * * @return \Illuminate\Http\JsonResponse */ public function refresh() { return $this->respondWithToken($this->guard()->refresh()); } /** * Get the token array structure. * * @param string $token * * @return \Illuminate\Http\JsonResponse */ protected function respondWithToken($token) { return response()->json([ 'access_token' => $token, 'token_type' => 'bearer', 'expires_in' => $this->guard()->factory()->getTTL() * 60 ]); } /** * Get the guard to be used during authentication. * * @return \Illuminate\Contracts\Auth\Guard */ public function guard() { return Auth::guard('api'); } }

現在你可以用有效的帳密發送請求到登入 API(例如:http://example.dev/api/login),收到的回應會像這樣:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vZXhhbXBsZS5kZXYvYXBpL2xvZ2luIiwiaWF0IjoxNTkyMjk4NjcwLCJleHAiOjE1OTIzMDIyNzAsIm5iZiI6MTU5MjI5ODY3MCwianRpIjoiSmVxUzVhQUxha0NUamhoUCIsInN1YiI6MSwicHJ2IjoiODdlMGFmMWVmOWZkMTU4MTJmZGVjOTcxNTNhMTRlMGIwNDc1NDZhYSJ9.KwU9iFp0vhSamDm1I0ExB9d_keK-mCkZfUBWlhWM4o4",
    "token_type": "bearer",
    "expires_in": 3600
}

然後就可以使用該 token 向你的應用程式發送經過身份驗證的請求。

發送已驗證的請求

可以使用多種方法透過 http 發送 token

  • 授權標頭(Authorization Header)

    Authorization: Bearer eyJ0eXAiOiJKV1QiLCJ...
  • 查詢字串參數(Query String Parameter)

    http://example.dev/me?token=eyJ0eXAiOiJKV1QiLCJ...

以上就是基本的使用 JWT 身份驗證實作 Laravel REST API 的部分,若有任何錯誤的地方也請多指教。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK