Laravel Sanctum vs Passport 2026: การยืนยันตัวตน API และคำถามสัมภาษณ์

คู่มือฉบับสมบูรณ์เปรียบเทียบ Laravel Sanctum และ Passport สำหรับการยืนยันตัวตน API พร้อมตัวอย่างโค้ดจริงและคำถามสัมภาษณ์ที่พบบ่อย

Laravel Sanctum vs Passport 2026: การยืนยันตัวตน API และคำถามสัมภาษณ์

Laravel Sanctum และ Passport ตอบโจทย์ความต้องการการยืนยันตัวตน API ที่แตกต่างกัน การเลือกแพ็กเกจที่ไม่เหมาะสมอาจนำไปสู่ความซับซ้อนที่ไม่จำเป็นหรือช่องโหว่ด้านความปลอดภัย คู่มือนี้อธิบายทั้งสองแพ็กเกจพร้อมตัวอย่างโค้ดจริงและคำถามสัมภาษณ์ที่เกี่ยวข้อง

การตัดสินใจอย่างรวดเร็ว

Sanctum จัดการการยืนยันตัวตน SPA และ API token แบบง่าย Passport ใช้งาน OAuth2 แบบเต็มรูปแบบพร้อม authorization codes, client credentials และ refresh tokens แอปพลิเคชันส่วนใหญ่ต้องการ Sanctum

Laravel Sanctum vs Passport: ความแตกต่างหลัก

Sanctum ให้การยืนยันตัวตนแบบ token ที่เบา ออกแบบมาสำหรับแอปพลิเคชัน first-party แพ็กเกจนี้ใช้การยืนยันตัวตน session แบบ cookie สำหรับ SPA และ personal access tokens สำหรับแอปมือถือและ API แบบง่าย

Passport ใช้งานข้อกำหนด OAuth2 อย่างครบถ้วน รวมถึง authorization servers, client credentials grants และการยืนยันตัวตน machine-to-machine ความซับซ้อนนี้จำเป็นสำหรับแอปพลิเคชันที่ต้องการอนุญาตการเข้าถึงจากบุคคลที่สาม

คุณสมบัติSanctumPassport
Use Case หลักSPA, แอปมือถือ, API แบบง่ายOAuth2 บุคคลที่สาม, Machine-to-Machine
ประเภท TokenToken hash แบบง่ายJWT พร้อม OAuth2 scopes
การยืนยันตัวตน Sessionใช่ (แบบ cookie)ไม่
OAuth2 Grantsไม่มีข้อกำหนดครบถ้วน
ขนาดแพ็กเกจเล็กใหญ่
การกำหนดค่าง่ายซับซ้อน

การใช้งาน Sanctum สำหรับการยืนยันตัวตน SPA

การยืนยันตัวตน SPA ของ Sanctum พึ่งพา session cookies ของ Laravel แทนที่จะเป็น API tokens Frontend และ backend ต้องแชร์ top-level domain เดียวกันเพื่อให้ทำงานได้

config/sanctum.phpphp
return [
    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

    'expiration' => null, // Token ไม่หมดอายุตามค่าเริ่มต้น

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],
];

SPA ต้องเรียก endpoint CSRF cookie ก่อนทำ request ที่ต้องการการยืนยันตัวตน ขั้นตอนนี้สร้าง session และตั้งค่า cookie XSRF-TOKEN

javascript
// Frontend: เริ่มต้นการป้องกัน CSRF ก่อนเข้าสู่ระบบ
async function initializeAuth() {
    await fetch('/sanctum/csrf-cookie', {
        credentials: 'include'
    });
}

async function login(email, password) {
    await initializeAuth();
    
    const response = await fetch('/api/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-XSRF-TOKEN': getCookie('XSRF-TOKEN'),
            'Accept': 'application/json'
        },
        credentials: 'include',
        body: JSON.stringify({ email, password })
    });
    
    return response.json();
}

การยืนยันตัวตน Token API ด้วย Sanctum

แอปพลิเคชันมือถือและการผสานรวมกับบุคคลที่สามใช้ personal access tokens แทน session cookies Sanctum เก็บ tokens เหล่านี้เป็น hash SHA-256 ในฐานข้อมูล

app/Http/Controllers/AuthController.phpphp
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    public function createToken(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
            'device_name' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        if (! $user || ! Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['ข้อมูลประจำตัวที่ให้มาไม่ถูกต้อง'],
            ]);
        }

        // Token พร้อม abilities (scopes)
        $token = $user->createToken(
            $request->device_name,
            ['read', 'write'] // Abilities ตัวเลือก
        );

        return response()->json([
            'token' => $token->plainTextToken,
            'expires_at' => null // กำหนดค่าใน sanctum.php
        ]);
    }

    public function revokeToken(Request $request)
    {
        // เพิกถอน token ปัจจุบัน
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'เพิกถอน Token สำเร็จ']);
    }
}

ป้องกัน routes ด้วย middleware auth:sanctum ใช้ method tokenCan เพื่อตรวจสอบ abilities ของ token

routes/api.phpphp
use Illuminate\Support\Facades\Route;

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

    Route::post('/posts', function (Request $request) {
        // ตรวจสอบว่า token มี ability write หรือไม่
        if (! $request->user()->tokenCan('write')) {
            abort(403, 'Token ไม่มีสิทธิ์ write');
        }

        // ตรรกะการสร้าง post
    });
});

พร้อมที่จะพิชิตการสัมภาษณ์ Laravel แล้วหรือยังครับ?

ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ

เมื่อใดควรใช้ Laravel Passport

Passport จำเป็นเมื่อแอปพลิเคชันทำหน้าที่เป็น authorization server OAuth2 สถานการณ์ทั่วไปได้แก่:

  • นักพัฒนาบุคคลที่สามสร้างการผสานรวมกับ API
  • การยืนยันตัวตน machine-to-machine ระหว่าง microservices
  • แอปพลิเคชันที่ต้องการความสอดคล้องกับ OAuth2 สำหรับลูกค้าองค์กร
  • ระบบที่ต้องการการหมุนเวียน refresh token และการตรวจสอบ JWT
app/Http/Controllers/Api/PassportController.phpphp
namespace App\Http\Controllers\Api;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;

class PassportController extends Controller
{
    public function issueToken(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        if (! $user || ! Hash::check($request->password, $user->password)) {
            return response()->json([
                'error' => 'invalid_credentials'
            ], 401);
        }

        // สร้าง token OAuth2 พร้อม scopes
        $token = $user->createToken('API Token', ['read-posts', 'write-posts']);

        return response()->json([
            'access_token' => $token->accessToken,
            'token_type' => 'Bearer',
            'expires_at' => $token->token->expires_at
        ]);
    }
}

Passport ยังรองรับ client credentials grant สำหรับการยืนยันตัวตน server-to-server โดยไม่ต้องมี context ของ user

php
// การยืนยันตัวตน machine-to-machine
// config/auth.php
'guards' => [
    'api' => [
        'driver' => 'passport',
        'provider' => 'users',
    ],
],

// routes/api.php - Route ที่ป้องกันด้วย client credentials
Route::middleware('client')->group(function () {
    Route::get('/machine-data', function () {
        return response()->json(['data' => 'เข้าถึงได้โดยเครื่อง']);
    });
});

แนวปฏิบัติด้านความปลอดภัยที่ดีที่สุดสำหรับการยืนยันตัวตน API Laravel

ทั้งสองแพ็กเกจต้องการมาตรการความปลอดภัยเพิ่มเติมนอกเหนือจากการตั้งค่าพื้นฐาน การหมดอายุของ token, การจำกัดอัตรา และการตรวจสอบ scope ที่เหมาะสมป้องกันช่องโหว่ทั่วไป

app/Providers/AuthServiceProvider.phpphp
namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;
use Laravel\Sanctum\PersonalAccessToken;

class AuthServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // ตั้งค่าการหมดอายุ token (Sanctum)
        Sanctum::authenticateAccessTokensUsing(function ($token, $isValid) {
            // Token หมดอายุหลัง 24 ชั่วโมง
            $expiration = config('sanctum.expiration');
            
            if ($expiration === null) {
                return $isValid;
            }

            return $isValid && $token->created_at->gt(now()->subMinutes($expiration));
        });
    }
}

ใช้งาน rate limiting บน endpoints การยืนยันตัวตนเพื่อป้องกันการโจมตี brute force Laravel 12 มีการกำหนดค่า rate limiter ที่ยืดหยุ่นผ่าน RateLimiting facade

app/Providers/AppServiceProvider.phpphp
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiting;

public function boot(): void
{
    RateLimiting::for('login', function ($request) {
        return Limit::perMinute(5)->by($request->ip());
    });

    RateLimiting::for('api', function ($request) {
        return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
    });
}

คำถามสัมภาษณ์เกี่ยวกับการยืนยันตัวตน Laravel

การสัมภาษณ์ทางเทคนิคมักทดสอบความเข้าใจเกี่ยวกับรูปแบบการยืนยันตัวตน API คำถามเหล่านี้ปรากฏในการสัมภาษณ์นักพัฒนา Laravel ทุกระดับ

ถ: ความแตกต่างระหว่างการยืนยันตัวตน SPA และการยืนยันตัวตน token ของ Sanctum คืออะไร?

การยืนยันตัวตน SPA ใช้ session cookies ของ Laravel พร้อมการป้องกัน CSRF Frontend เรียก /sanctum/csrf-cookie เพื่อสร้าง session จากนั้น requests ถัดไปจะรวม session cookie โดยอัตโนมัติ การยืนยันตัวตน token ใช้ Bearer tokens ใน Authorization header เหมาะสำหรับแอปมือถือและการผสานรวมกับบุคคลที่สามที่ cookies ไม่สะดวก

ถ: เมื่อใดควรเลือก Passport แทน Sanctum?

Passport ใช้งาน OAuth2 แบบเต็ม จำเป็นเมื่อนักพัฒนาบุคคลที่สามต้องการผสานรวมกับ API โดยใช้ authorization code flow หรือเมื่อการยืนยันตัวตน machine-to-machine ต้องการ client credentials grants Sanctum จัดการแอปพลิเคชัน first-party ได้ง่ายกว่า

ถ: Sanctum เก็บ API tokens อย่างไร?

Sanctum เก็บ hash SHA-256 ของแต่ละ token ในตาราง personal_access_tokens Token แบบ plain text จะส่งคืนเพียงครั้งเดียวตอนสร้าง วิธีนี้หมายความว่าข้อมูลฐานข้อมูลที่ถูกบุกรุกไม่สามารถเปิดเผย tokens ที่ใช้งานได้

ถ: จะใช้งาน abilities/scopes ของ token ใน Sanctum อย่างไร?

php
// สร้าง token พร้อม abilities
$token = $user->createToken('api-token', ['posts:read', 'posts:write']);

// ตรวจสอบ abilities ใน controller
if ($request->user()->tokenCan('posts:write')) {
    // ได้รับอนุญาตสำหรับการดำเนินการ write
}

// การตรวจสอบ ability แบบ middleware
Route::middleware(['auth:sanctum', 'ability:posts:write'])
    ->post('/posts', [PostController::class, 'store']);

ถ: จะเพิกถอน tokens ทั้งหมดสำหรับ user ใน Sanctum อย่างไร?

php
// เพิกถอน tokens ทั้งหมด
$user->tokens()->delete();

// เพิกถอน token เฉพาะตาม ID
$user->tokens()->where('id', $tokenId)->delete();

// เพิกถอนเฉพาะ token ปัจจุบัน
$request->user()->currentAccessToken()->delete();

การย้ายจาก Passport ไปยัง Sanctum

แอปพลิเคชันที่เริ่มต้นด้วย Passport แต่ใช้เฉพาะการยืนยันตัวตน token แบบง่ายสามารถย้ายไปยัง Sanctum เพื่อลดความซับซ้อน การย้ายต้องอัปเดตการสร้าง token, การกำหนดค่า middleware และการตรวจสอบ scope

php
// ตัวช่วยการย้าย: แปลง tokens Passport เป็น Sanctum
use App\Models\User;
use Laravel\Passport\Token;

// นี่คือการย้ายแบบทางเดียว - รันครั้งเดียวแล้วลบ Passport
User::chunk(100, function ($users) {
    foreach ($users as $user) {
        $passportTokens = Token::where('user_id', $user->id)
            ->where('revoked', false)
            ->get();

        foreach ($passportTokens as $token) {
            $user->createToken(
                $token->name ?? 'migrated-token',
                $token->scopes ?? []
            );
        }
    }
});

อัปเดต middleware ของ route จาก auth:api เป็น auth:sanctum และแทนที่ $request->user()->token()->scopes ด้วย $request->user()->currentAccessToken()->abilities

บทสรุป

  • Sanctum เหมาะกับ SPA, แอปมือถือ และ API first-party ด้วยการกำหนดค่าน้อยที่สุด
  • Passport จัดการ authorization server OAuth2 และการผสานรวมกับบุคคลที่สาม
  • การยืนยันตัวตน SPA ใช้ session cookies; การยืนยันตัวตน API ใช้ Bearer tokens
  • Token abilities ให้การควบคุมสิทธิ์ที่ละเอียดใน Sanctum
  • Rate limiting และการหมดอายุ token เป็นมาตรการความปลอดภัยที่จำเป็นไม่ว่าจะเลือกแพ็กเกจใด
  • แอปพลิเคชัน Laravel ส่วนใหญ่ควรเริ่มต้นด้วย Sanctum และเพิ่ม Passport เมื่อความสอดคล้องกับ OAuth2 กลายเป็นข้อกำหนด

เริ่มฝึกซ้อมเลย!

ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ

ชาเลนจ์ประจำวัน

คุณหาบั๊กใน Laravel เจอไหม

โค้ดจริงหนึ่งชิ้น บั๊กที่ซ่อนอยู่หนึ่งจุด วันละหนึ่งครั้ง ลองได้โดยไม่ต้องมีบัญชี

Anthony Fillion-Maillet

เขียนโดย

Anthony Fillion-Maillet

ผู้ก่อตั้ง SharpSkill

เป็นนักพัฒนาฟูลสแตกมากว่า 10 ปี ดูแล SharpSkill และรับผิดชอบทุกสิ่งที่เผยแพร่ที่นี่

อัปเดตเมื่อ 26 กรกฎาคม 2569

แชร์

บทความที่เกี่ยวข้อง