使用 JWT 認證使用者身份

laradocs發表於2021-11-09

前言

什麼是 JWT?

Json web token (JWT), 是為了在網路應用環境間傳遞宣告而執行的一種基於JSON的開放標準((RFC 7519).該token被設計為緊湊且安全的,特別適用於分散式站點的單點登入(SSO)場景。JWT的宣告一般被用來在身份提供者和服務提供者間傳遞被認證的使用者身份資訊,以便於從資源伺服器獲取資源,也可以增加一些額外的其它業務邏輯所必須的宣告資訊,該token也可直接被用於認證,也可被加密。

通過 composer 安裝

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

composer require tymon/jwt-auth

注意: 如果報錯以下資訊:

Your requirements could not be resolved to an installable set of packages.

Problem 1
    - Root composer.json requires tymon/jwt-auth ^0.5.12 -> satisfiable by tymon/jwt-auth[0.5.12].
    - tymon/jwt-auth 0.5.12 requires illuminate/support ~5.0 -> found illuminate/support[v5.0.0, ..., 5.8.x-dev] but these were not loaded, likely because it conflicts with another require.

You can also try re-running composer require with an explicit version constraint, e.g. "composer require tymon/jwt-auth:*" to figure out if any version is installable, or "composer require tymon/jwt-auth:^2.1" if you know which you need.

Installation failed, reverting ./composer.json and ./composer.lock to their original content.

那麼就重新執行以下命令:

composer require tymon/jwt-auth "*"

釋出配置檔案

我們可以執行以下命令釋出配置檔案:

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

現在你的 config 會多出一個 jwt.php 檔案。

生成金鑰

我們可以使用 jwt-auth 包自帶的助手命令來生成金鑰:

php artisan jwt:secret

這將會在 .env 檔案中追加類似於 JWT_SECRET=... 的內容。

配置 User 模型

首先,讓我們大致瞭解一下 jwt-auth 包。要想使用 jwt 認證使用者身份證,我們還需在 User 模型上實現 Tymon\JWTAuth\Contracts\JWTSubject 契約,那麼這個該怎麼實現呢?

我們可以開啟 JWTSubject.php 檔案檢視究竟:

vendor/tymon/jwt-auth/src/Contracts/JWTSubject.php

<?php

namespace Tymon\JWTAuth\Contracts;

interface JWTSubject
{
    public function getJWTIdentifier();

    public function getJWTCustomClaims();
}

可以看到 JWTSubject 契約裡面有兩個方法。

接下來,我們將在 User 模型裡面實現這兩個方法:

app/Models/User.php

<?php

namespace App\Models;

.
.
.
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    .
    .
    .
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }
}

很棒?看到這裡,說明你已經完成 99% 了。繼續之前,先給自己鼓個掌吧。

配置認證守衛

最後,我們還需配置一下 auth.php 檔案。

config/app.php

<?

return [
    'defaults' => [
        'guard' => 'api',
        'passwords' => 'users',
    ],

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'jwt',
            'provider' => 'users',
        ]
    ],

    .
    .
    .
];

這裡我們告訴 api 守衛使用 jwt 驅動程式,我們將 api 守衛設定為預設。

超級棒?你完成了整個 jwt 配置。

新增路由

在正式開始使用 jwt 之前,我們還需要在 api.php 檔案中新增一些路由:

routes/api.php

Route::group ( [

    'prefix' => 'auth',

], function ( $router ) {

    $router->post ( 'login', 'AuthController@login' );
    $router->post ( 'logout', 'AuthController@logout' );
    $router->post ( 'refresh', 'AuthController@refresh' );
    $router->post ( 'me', 'AuthController@me' );

} );

建立控制器

我們可以執行以下命令快速建立控制器:

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
{
    public function __construct()
    {
        $this->middleware ( 'auth:api' )->except ( 'login' );
    }

    public function login()
    {
        $credentials = request ( [ 'email', 'password' ] );
        if ( ! $token = auth ( 'api' )->attempt ( $credentials ) ) {
            return response()->json ( [
                'error' => 'Unauthorized.'
            ], 401 );
        }

        return $this->respondWithToken($token);
    }

    public function logout()
    {
        auth ( 'api' )->logout();

        return response()->json ( [
            'message' => 'Successfully logged out',
        ] );
    }

    public function me()
    {
        return response()->json ( auth ( 'api' )->user() );
    }

    public function refresh()
    {
        return $this->respondWithToken(auth ( 'api' )->refresh());
    }

    protected function respondWithToken ( $token )
    {
        return response()->json ( [
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth ( 'api' )->factory()->getTTL() * 60,
        ] );
    }
}

測試環節

在進入測試環節之前,我們要先檢查一下細節:

  • app/Providers/RouteServiceProvider.php 檔案中的第 29 行是否取消註釋
  • .env 檔案中的資料庫是否配置正確

建立使用者

我們可以執行以下命令進入 tinker 環境:

php artisan tinker

接下來建立一個使用者:

>>> App\Models\User::create ( [ 'name' => 'laradocs', 'email' => 'laradocs@example.com', 'password' => bcrypt('123456') ] );
=> App\Models\User {#4404
     name: "laradocs",
     email: "laradocs@example.com",
     #password: "$2y$10$/pjfmnRSQs1S24vY86qKe.U4akfKVQwiKXy7dp3WCsefYym4oc.S.",
     updated_at: "2021-11-09 04:04:37",
     created_at: "2021-11-09 04:04:37",
     id: 1,
   }

測試登入

我這裡使用的是 postman,你也可以選擇你擅長的軟體。

登入失敗示例:

使用 JWT 認證使用者身份

登入成功示例:

使用 JWT 認證使用者身份

個人資訊

要保持登入狀態,我們需要複製 access_token 放到 AuthorizationBearer TokenToken 中:

使用 JWT 認證使用者身份

重新整理 token

使用 JWT 認證使用者身份

注意:我們需要把 Token 裡面的 token 替換成重新整理後的 token,否則將會出現以下提示:
使用 JWT 認證使用者身份

還有一個退出測試,你們就自己嘗試一下吧。
好了,測試環節就到這裡了。

如果你想了解更多對你有用的資訊,請戳這裡 ? jwt-auth 中文文件

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章