Skip to content

PlusMagi's Blog By Pitt Phunsanit

Plus emotional magic to the knowledge of logic.

  • About’s Pitt
Close Button

PHP: การใช้ password_hash() และ password_verify() สำหรับระบบรหัสผ่านPHP: การใช้ password_hash() และ password_verify() สำหรับระบบรหัสผ่าน

2012-04-222012-04-22| phunsanitphunsanit| 0 Comment | 07:00

ในโลกของการพัฒนาเว็บแอปพลิเคชัน การจัดการรหัสผ่านของผู้ใช้งานถือเป็นหัวใจหลักของความปลอดภัย (Security) อย่างยิ่ง ในอดีต นักพัฒนามักใช้ฟังก์ชันการเข้ารหัสแบบมาตรฐาน เช่น MD5, SHA-1 หรือ SHA-256 เพื่อ “แฮช” (Hash) รหัสผ่าน แต่แนวทางนี้ถูกพิสูจน์แล้วว่าไม่เพียงพอต่อการป้องกันในปัจจุบัน เนื่องจากฟังก์ชันเหล่านี้เป็น One-way function ที่เมื่อทราบค่า Hash แล้ว การถอดรหัสกลับไปหา Password ต้นฉบับนั้นทำได้ง่ายด้วยเทคนิค Brute Force หรือ Rainbow Table

PHP ได้พัฒนาชุดฟังก์ชันเฉพาะทางขึ้นมาเพื่อแก้ไขปัญหานี้ นั่นคือ password_hash() และ password_verify() ฟังก์ชันเหล่านี้ไม่ได้เพียงแค่ “แฮช” ข้อมูลเท่านั้น แต่ยังรวมเอาหลักการสำคัญด้านความปลอดภัยที่เรียกว่า Salt (ค่าสุ่มที่ไม่ซ้ำกัน) เข้าไปในกระบวนการโดยอัตโนมัติ และที่สำคัญที่สุดคือใช้กลไก Adaptive Hashing ซึ่งหมายถึงการทำให้กระบวนการแฮชมีความ “หน่วง” (Computational Cost) เพื่อให้แม้ผู้โจมตีจะสามารถคำนวณ Hash ได้จำนวนมาก ก็ต้องใช้เวลาและทรัพยากรสูงมากจนไม่คุ้มค่า

หลักการทำงานโดยสรุป:

  • password_hash(): ใช้สำหรับ “สร้าง” (Generate) Hash ของรหัสผ่าน โดยรับ Password ต้นฉบับและส่งออกเป็นสตริง Hash ที่มีข้อมูล Meta Data (เช่น Algorithm, Cost Factor และ Salt) ฝังอยู่ด้วย
  • password_verify(): ใช้สำหรับ “ตรวจสอบ” (Verify) ว่ารหัสผ่านที่ผู้ใช้ป้อนเข้ามานั้นตรงกับ Hash ที่ถูกจัดเก็บไว้ในฐานข้อมูลหรือไม่ โดยฟังก์ชันนี้จะดึงค่า Meta Data จาก Hash เก่ามาใช้ในการคำนวณ และเปรียบเทียบผลลัพธ์โดยไม่เปิดเผย Password ต้นฉบับ

ตัวอย่างการใช้งานและรูปแบบโค้ด (Code Examples)

เราจะจำลองกระบวนการ 2 ขั้นตอนหลัก คือ การลงทะเบียนผู้ใช้ (Hashing) และการเข้าสู่ระบบ (Verification)

<?php

// -------------------------------------------
// ส่วนที่ 1: การลงทะเบียนผู้ใช้ (Hashing)
// -------------------------------------------

/**
 * ฟังก์ชันสำหรับสร้าง Hash ของรหัสผ่าน
 * @param string $password รหัสผ่านต้นฉบับ
 * @return string Hash ที่เข้ารหัสแล้ว
 */
function hash_password(string $password): string {
    // PASSWORD_DEFAULT จะเลือก Algorithm ที่ปลอดภัยที่สุดตาม PHP Version (เช่น Bcrypt หรือ Argon2)
    // การระบุ cost เป็นการเพิ่มความยากในการคำนวณ
    $options = [
        'cost' => 12 // ค่า Cost เริ่มต้นที่ปลอดภัย
    ];

    $hash = password_hash($password, PASSWORD_DEFAULT, $options);

    if ($hash === false) {
        throw new \RuntimeException("Error: ไม่สามารถสร้าง Hash ได้ กรุณาลองใหม่อีกครั้ง");
    }
    return $hash;
}

// สมมติว่าผู้ใช้ป้อนรหัสผ่าน "MySecretPass123"
$plain_password = "MySecretPass123";
$stored_hash = hash_password($plain_password);

echo "========================================\n";
echo "รหัสผ่านต้นฉบับ: " . htmlspecialchars($plain_password) . "\n";
echo "Hash ที่จัดเก็บในฐานข้อมูล (Stored Hash):\n" . $stored_hash . "\n";
echo "----------------------------------------\n\n";


// -------------------------------------------
// ส่วนที่ 2: การเข้าสู่ระบบ (Verification)
// -------------------------------------------

/**
 * ฟังก์ชันสำหรับตรวจสอบรหัสผ่านเมื่อผู้ใช้ล็อกอิน
 * @param string $plain_password รหัสผ่านที่ผู้ใช้ป้อนเข้ามา
 * @param string $stored_hash Hash ที่ถูกดึงมาจากฐานข้อมูล
 * @return bool True หากรหัสผ่านถูกต้อง, False หากไม่ถูกต้อง
 */
function verify_password(string $plain_password, string $stored_hash): bool {
    // password_verify จะทำการแยกค่า Salt และ Algorithm จาก $stored_hash โดยอัตโนมัติ
    $is_valid = password_verify($plain_password, $stored_hash);

    if ($is_valid) {
        echo "✅ การตรวจสอบสำเร็จ: รหัสผ่านถูกต้อง!";
    } else {
        echo "❌ การตรวจสอบล้มเหลว: รหัสผ่านไม่ถูกต้อง";
    }
    return $is_valid;
}

// 1. ทดสอบด้วยรหัสผ่านที่ถูกต้อง
$login_attempt_success = verify_password("MySecretPass123", $stored_hash);
echo "\n\n[Test Success]: " . ($login_attempt_success ? 'SUCCESS' : 'FAIL') . "\n";

// 2. ทดสอบด้วยรหัสผ่านที่ผิดพลาด
$login_attempt_fail = verify_password("WrongPassword!", $stored_hash);
echo "\n[Test Failure]: " . ($login_attempt_fail ? 'SUCCESS' : 'FAIL');

?>

ข้อควรระวัง Security และ Best Practices

  • คำนึงถึงความปลอดภัย (Security): ห้ามใช้ฟังก์ชันแฮชแบบเก่าเด็ดขาด (MD5, SHA) ควรใช้ password_hash() เสมอ เนื่องจากมันจัดการ Salt และ Algorithm ที่เหมาะสมให้โดยอัตโนมัติ นอกจากนี้ ในการใช้งานจริง ต้องมั่นใจว่ารหัสผ่านที่ผู้ใช้ป้อนเข้ามานั้นเป็นค่า String ที่สะอาดและไม่มีช่องโหว่จากการ Injection (ควรมีการ Validate Input เสมอ)
  • Performance (Cost Factor): พารามิเตอร์ cost ใน password_hash() คือตัวกำหนดความยากในการคำนวณ การเพิ่มค่า Cost จะทำให้ระบบปลอดภัยยิ่งขึ้น แต่ก็จะใช้เวลา CPU มากขึ้นด้วย ดังนั้น ควรหาจุดสมดุลระหว่างความปลอดภัยและประสิทธิภาพของเซิร์ฟเวอร์ (โดยทั่วไป ค่า 10-12 ถือว่าเหมาะสมสำหรับปัจจุบัน)
  • Error Handling: ต้องมีการตรวจสอบผลลัพธ์จากทั้งสองฟังก์ชันเสมอ โดยเฉพาะการตรวจสอบว่าค่าที่ส่งกลับมาเป็น false หรือไม่ เพื่อป้องกันการทำงานต่อด้วย Hash ที่ผิดพลาด และควรใช้ Try-Catch Block ในส่วนของการจัดการฐานข้อมูลเพื่อความสมบูรณ์ของโค้ด

สรุปและการนำไปประยุกต์ใช้งาน

การใช้ password_hash() และ password_verify() ไม่ใช่แค่ทางเลือก แต่เป็นมาตรฐานความปลอดภัยที่จำเป็น (Mandatory Standard) สำหรับทุกแอปพลิเคชัน PHP ที่มีการจัดการรหัสผ่านของผู้ใช้งาน การทำเช่นนี้ช่วยให้ระบบของคุณสามารถป้องกันผู้โจมตีจากการเข้าถึงข้อมูลรหัสผ่านแม้ว่าฐานข้อมูลจะถูกขโมยไปก็ตาม


สรุปขั้นตอนการทำงานใน Production:

  • Registration: รับ Password -> เรียก password_hash() -> เก็บ Hash ที่ได้ลงในคอลัมน์รหัสผ่านของฐานข้อมูล
  • Login: ดึง Hash จาก DB -> รับ Password ที่ผู้ใช้ป้อน -> เรียก password_verify() เพื่อเปรียบเทียบ -> ถ้าเป็นจริง (True) ให้ถือว่าล็อกอินสำเร็จ

การทำความเข้าใจและนำหลักการเหล่านี้ไปใช้อย่างถูกต้อง จะช่วยยกระดับความปลอดภัยของระบบ PHP ของคุณให้ทัดเทียมกับมาตรฐานระดับสากลได้อย่างสมบูรณ์


อ่านเพิ่มเติม

  • PHP: การใช้งาน random_bytes() และ random_int() สำหรับข้อมูลสุ่มที่ปลอดภัย
  • PHP: การตรวจสอบและจำกัดประเภทไฟล์อัปโหลด (Mime Type Validation)
  • PHP: การตั้งค่า Session Cookie (Secure, HttpOnly, SameSite)
Read MoreRead More

Posts pagination

ก่อนหน้า 1 … 920 921 922 … 1,209 ถัดไป

Projects

  • Statement Columns Mapping Helper
  • PlusMagi Site Search
  • jQuery Plus Repeater

Recent Posts

  • Linux: ตรวจสอบความถูกต้องของระบบด้วยสปีดขั้นสุด 🚀
  • Tarball: เป็น version control ?
  • SecDevOps: เปลี่ยนความปลอดภัยให้เป็นเนื้อเดียวกับ Code และ Operation
  • WordPress: ดูว่า post ทุก ๆ วันเสาร์ใช่มั๋ย
  • เทคนิคตั้งค่า umask 002 ให้กับทุก User บน Mac อัตโนมัติผ่าน Terminal (Batch Script)

Archives

Categories

  • AI (26)
  • Businesses (28)
  • Design (56)
    • UX/UI (22)
  • Histories (16)
  • Life (120)
    • Books (51)
    • Cartoon (6)
    • Movies (11)
    • Sci-Fi (20)
    • Tips and Tricks (26)
    • พุทธ (7)
  • Network (147)
    • Apache HTTP Server (17)
    • IOT (1)
    • Nginx (31)
    • Stalwart (6)
  • Operating Systems (282)
    • Unix-like (207)
      • Android (16)
        • F-Droid (5)
      • Homebrew (21)
      • iPhone (8)
      • Linux (120)
      • macOS (100)
        • OrbStack (11)
      • Oh My ZSH (4)
      • Shell Script (42)
      • SSH (11)
    • Windows (121)
      • PowerShell (26)
      • WSL (25)
  • Programming (822)
    • .NET (20)
      • .NET Core EF (6)
      • C# (18)
    • API (39)
      • REST (8)
      • Swagger (7)
    • Database (189)
      • DBeaver (3)
      • MariaDB (32)
      • MySql (69)
      • Oracle Database (6)
        • 10g (3)
      • PostgreSQL (9)
      • RDBMS (2)
      • SQL Server (85)
        • SSMS (8)
        • T-SQL (26)
      • SQLite (1)
    • PowerBuilder (11)
    • Python (6)
    • Rust (5)
    • System Analyst (SA) (37)
    • Testing (27)
      • Automated Testing (13)
        • Playwright (6)
    • UML (7)
    • Web (447)
      • Backend (303)
        • Golang (2)
        • Java (49)
          • Spring Boot (14)
        • Node.js (3)
        • PHP (254)
          • Laravel (50)
          • Yii (5)
      • Frontend (136)
        • CSS (18)
          • Tailwind CSS (5)
        • JavaScript (123)
          • Angular (3)
          • jQuery (62)
          • Tabulator (19)
          • Vue.js (5)
      • WordPress (26)
  • Programs (104)
    • Excel (12)
  • SecDevOps (97)
    • CI/CD (10)
    • Docker (41)
    • GIT (34)
  • Security (126)
  • Uncategorized (6)
  • กฎหมาย (9)

Sirat WordPress Theme By VWThemes

Scroll Up
Exit mobile version