iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
Modern Web

後端菜雞仔想學 Laravel系列 第 25

建立註冊、登入、登出流程:再指派一位店長吧!

  • 分享至 

  • xImage
  •  

小食譜06:處理認證與授權

昨天簡單介紹了 JWT 認證機制,今天我們就來試試看!

安裝 tymon/jwt-auth 套件

這是一個用於 Laravel 框架的套件,專門設計來處理基於 JWT 的無狀態身份驗證。

更多相關資訊及安裝指令可以參考:JWTAuth 官方文件

安裝完套件後來建立密鑰

JWT 使用一個密鑰來簽署 Token,所以先建立這個密鑰:

php artisan jwt:secret

這個指令會在你的 .env 檔案中加入一個 JWT_SECRET,這是用來保護和驗證 Token 的重要密鑰。

設定 User 模型

讓 User 模型實現 JWTSubject 介面,這樣可以告訴 JWT 如何處理使用者資料。

修改 User.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;

    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    protected $hidden = [
        'password',
        'remember_token',
    ];

    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

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

這兩個方法是 JWT Token 生成過程中的核心部分:

  • getJWTIdentifier()
    負責告訴 JWT 這個 Token 屬於哪個使用者,通常是用「使用者的 id」。

  • getJWTCustomClaims()
    允許你在 JWT 中加入額外的資訊,這樣可以在不查詢資料庫的情況下快速讀取一些常用的使用者屬性。

更新認證 Guard

JWT 是用來取代 Laravel 預設的 Session 驗證,所以要修改 config/auth.php,將 API 的 guard 改為 jwt。

找到 guards 區塊,將 driver 從 token 改為 jwt:

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

建立註冊、登入、登出功能範例

首先,建立一個 AuthController,也就是再指派一位專門處理這些功能的店長。

AuthController:

<?php

class AuthController extends Controller
{
    // 註冊方法
    public function register(Request $request)
    {
        // 使用 Validator 對請求資料進行驗證
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',  // 名字必填,字串類型,最大長度255
            'email' => 'required|string|email|max:255|unique:users',  // email必填,字串類型,格式為email,最大長度255,且在 users 表中必須唯一
            'password' => 'required|string|min:6|confirmed',  // 密碼必填,字串類型,最小長度為6,且需要確認
        ]);

        // 如果驗證失敗,回傳錯誤訊息
        if($validator->fails()){
            return response()->json($validator->errors(), 400);  // 回傳400狀態碼和錯誤訊息
        }

        // 創建新的使用者
        $user = User::create([
            'name' => $request->name,  // 從請求中取得名字
            'email' => $request->email,  // 從請求中取得email
            'password' => Hash::make($request->password),  // 將密碼進行亂碼處理
        ]);

        // 為新建立的使用者生成 JWT
        $token = JWTAuth::fromUser($user);

        // 回傳新使用者資料和 JWT,狀態碼為201
        return response()->json(compact('user','token'), 201);
    }

    // 登入方法
    public function login(Request $request)
    {
        // 只從請求中取得 email 和 password 欄位
        $credentials = $request->only('email', 'password');

        // 使用 JWTAuth 進行驗證
        if (! $token = JWTAuth::attempt($credentials)) {
            return response()->json(['error' => 'Unauthorized'], 401);  // 驗證失敗,回傳401未授權
        }

        // 驗證成功,回傳 JWT
        return response()->json(compact('token'));
    }

    // 登出方法
    public function logout(Request $request)
    {
        $token = $request->bearerToken();
        if (!$token) {
            return response()->json(['error' => '需要提供token'], 401);
        }
        auth()->logout($token);
        return response()->json(['message' => '您已登出成功!'], 200);
    }
    
}

註冊邏輯

  1. 驗證請求資料。
  2. 如果驗證失敗,回傳錯誤訊息。
  3. 建立新的使用者,並將密碼進行雜湊。
  4. 為新的使用者生成 JWT。
  5. 回傳新的使用者資料和 JWT。

登入邏輯

  1. 從請求中取得 email 和 password。
  2. 使用 JWTAuth 嘗試驗證使用者。
  3. 如果驗證失敗,回傳未授權錯誤。
  4. 如果驗證成功,回傳 JWT。

登出邏輯

  1. 取得 Token。
  2. 如果沒有 Token 則回傳錯誤回應。
  3. 讓該使用者登出並將這個 Token 作廢。
  4. 回傳成功登出的訊息。

分配店員:設定路由

api.php:

use App\Http\Controllers\AuthController;

Route::post('register', [AuthController::class, 'register']);
Route::post('login', [AuthController::class, 'login']);
Route::post('logout', [AuthController::class, 'logout'])->middleware('auth:api');

分配執行特殊任務的店員:

可以使用 auth:api 中介層來保護需要身份驗證的路由。

我的理解

例如:登入後需要取得會員資料,要再次驗證 token 成功!

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

更多相關資訊可以參考:


使用 Postman 測試

註冊

輸入註冊資料,按下 Send 後:

https://ithelp.ithome.com.tw/upload/images/20241009/20169300816BSIVMDJ.png

出現一個 token 即為成功註冊!

登入

選擇 Bearer Token:{{token}}

https://ithelp.ithome.com.tw/upload/images/20241009/20169300yQlmrYASrp.jpg

輸入 email 跟 密碼,按下 Send 後:

https://ithelp.ithome.com.tw/upload/images/20241009/20169300wxXaTK7KqL.png

出現一個 token 即為成功登入!

取得使用者資料

選擇 Bearer Token:{{token}}

https://ithelp.ithome.com.tw/upload/images/20241009/20169300tXpMkPn5z5.jpg

按下 Send 後:

{
    "id": 2,
    "name": "Test User2",
    "email": "test2@example.com",
    "email_verified_at": null,
    "created_at": "2024-08-27 15:18",
    "updated_at": "2024-08-27 15:18"
}

出現使用者資料即為成功!

登出

選擇 Bearer Token:{{token}}
按下 Send 後:

https://ithelp.ithome.com.tw/upload/images/20241009/20169300FmOSYZQiNS.jpg

出現設定好的訊息即為成功登出!


上一篇
JWT 認證機制:拿好你當天購買的門票,明天進來要再重新買一張!
下一篇
Middleware 會員權限設計:做出工作識別證!
系列文
後端菜雞仔想學 Laravel30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言