メインコンテンツへ移動

เนื้อหาภาษาไทย / タイ語のコンテンツ

システムガイド 内容確認済み

Password Hashing: การใช้งาน password_hash() เบื้องต้น

บทความนี้อธิบายถึงความสำคัญของการใช้ password hashing เพื่อเก็บรักษารหัสผ่านของผู้ใช้ให้ปลอดภัย โดยแนะนำให้ใช้ฟังก์ชัน `password_hash()` ของ PHP ซึ่งรองรับ algo...

Password Hashing: การใช้งาน password_hash() เบื้องต้น

ในบทเรียนก่อนหน้า เราได้เรียนรู้เกี่ยวกับการป้องกัน CSRF (Cross-Site Request Forgery) ซึ่งเป็นส่วนสำคัญในการรักษาความปลอดภัยของเว็บแอปพลิเคชัน ในบทนี้ เราจะมาเรียนรู้เกี่ยวกับการเก็บรหัสผ่านของผู้ใช้ให้ปลอดภัย โดยใช้ฟังก์ชัน password_hash() ของ PHP ซึ่งเป็นวิธีที่แนะนำในการเก็บรหัสผ่านในปัจจุบัน

การเก็บรหัสผ่านแบบ plaintext (ข้อความธรรมดา) เป็นสิ่งที่อันตรายอย่างยิ่ง หากฐานข้อมูลถูกแฮกเกอร์เข้าถึงได้ รหัสผ่านทั้งหมดของผู้ใช้จะถูกเปิดเผยทันที ดังนั้น เราจึงต้องแปลงรหัสผ่านให้เป็นรูปแบบที่ไม่สามารถอ่านได้ง่ายๆ หรือที่เรียกว่า "hash" ซึ่ง password_hash() ช่วยให้เราทำสิ่งนี้ได้อย่างง่ายดายและปลอดภัย

ทำไมต้อง Password Hashing?

Password Hashing คือกระบวนการแปลงรหัสผ่านให้เป็นสายอักขระที่ซับซ้อนและไม่สามารถย้อนกลับได้ (one-way function) ซึ่งหมายความว่า เราสามารถตรวจสอบได้ว่ารหัสผ่านที่ผู้ใช้ป้อนนั้นถูกต้องหรือไม่ โดยไม่ต้องเก็บรหัสผ่านจริงไว้ในฐานข้อมูล

วิธีการ hashing แบบเก่า เช่น MD5 หรือ SHA1 ไม่ปลอดภัยอีกต่อไป เนื่องจากมีเครื่องมือที่สามารถ "crack" หรือถอดรหัส hash เหล่านี้ได้ง่าย password_hash() ใช้ algorithm ที่แข็งแกร่งกว่า เช่น bcrypt (ค่าเริ่มต้น) หรือ Argon2i ซึ่งออกแบบมาเพื่อป้องกันการโจมตีด้วย brute-force และ rainbow table

การใช้งาน password_hash()

ฟังก์ชัน password_hash() รับพารามิเตอร์สองตัว:

  1. รหัสผ่าน: รหัสผ่านที่ต้องการ hash (string)
  2. Algorithm: Algorithm ที่ใช้ในการ hashing (integer หรือ string)
  3. Options (optional): อาร์เรย์ของตัวเลือกเพิ่มเติม เช่น cost สำหรับ bcrypt หรือ memory_cost, time_cost, และ threads สำหรับ Argon2i

ตัวอย่าง:

<?php

$password = "mySecretPassword123";

// ใช้ bcrypt algorithm (ค่าเริ่มต้น)
$hashedPassword = password_hash($password, PASSWORD_DEFAULT);

echo "Hashed password: " . $hashedPassword . "<br>";

// ใช้ Argon2i algorithm (ต้องใช้ PHP 7.2 ขึ้นไป)
// $options = ['memory_cost' => 2048, 'time_cost' => 4, 'threads' => 2];
// $hashedPassword = password_hash($password, PASSWORD_ARGON2I, $options);

// echo "Hashed password (Argon2i): " . $hashedPassword . "<br>";

?>

คำอธิบาย:

  • PASSWORD_DEFAULT คือค่าคงที่ที่กำหนด algorithm ที่แนะนำให้ใช้ (ปัจจุบันคือ bcrypt) การใช้ PASSWORD_DEFAULT ทำให้โค้ดของคุณมีความยืดหยุ่นมากขึ้น เพราะ PHP อาจเปลี่ยน algorithm ที่แนะนำในอนาคต และโค้ดของคุณจะยังคงทำงานได้โดยไม่ต้องแก้ไข
  • การใช้ Argon2i (PASSWORD_ARGON2I) เหมาะสำหรับระบบที่ต้องการความปลอดภัยสูงเป็นพิเศษ แต่ต้องใช้ PHP 7.2 ขึ้นไป และอาจต้องปรับค่า memory_cost, time_cost, และ threads ให้เหมาะสมกับทรัพยากรของ server

การเลือก Algorithm

การเลือก algorithm ที่เหมาะสมขึ้นอยู่กับความต้องการด้านความปลอดภัยและประสิทธิภาพของระบบของคุณ

  • bcrypt (PASSWORD_DEFAULT): เป็น algorithm ที่แนะนำให้ใช้โดยทั่วไป มีความปลอดภัยสูงและทำงานได้ดีบน server ส่วนใหญ่
  • Argon2i (PASSWORD_ARGON2I): เป็น algorithm ที่ทันสมัยกว่า bcrypt และมีความต้านทานต่อการโจมตีด้วย hardware ที่เฉพาะเจาะจง (เช่น GPU) มากกว่า แต่ต้องการทรัพยากรมากกว่าและอาจไม่พร้อมใช้งานบน server ทุกเครื่อง

หากคุณไม่แน่ใจว่าจะเลือก algorithm ใด ให้ใช้ PASSWORD_DEFAULT ซึ่งเป็นตัวเลือกที่ปลอดภัยและยืดหยุ่นที่สุด

การสร้าง Salt

password_hash() จะสร้าง "salt" โดยอัตโนมัติ ซึ่งเป็นข้อมูลสุ่มที่ใช้ในการเพิ่มความซับซ้อนให้กับ hash Salt ช่วยป้องกันการโจมตีด้วย rainbow table ซึ่งเป็นตารางที่เก็บ hash ของรหัสผ่านที่พบบ่อย

สำคัญ: คุณไม่จำเป็นต้องสร้าง salt เอง password_hash() จะจัดการเรื่องนี้ให้คุณโดยอัตโนมัติ

การเก็บ Hash ในฐานข้อมูล

เมื่อคุณได้ hash ของรหัสผ่านแล้ว คุณจะต้องเก็บ hash นี้ไว้ในฐานข้อมูล เพื่อใช้ในการตรวจสอบรหัสผ่านของผู้ใช้ในภายหลัง

ข้อควรระวัง:

  • ขนาดของ field: hash ที่สร้างโดย password_hash() อาจมีความยาว ดังนั้น ตรวจสอบให้แน่ใจว่า field ในฐานข้อมูลของคุณมีขนาดเพียงพอที่จะเก็บ hash ได้ โดยทั่วไป field ที่มีขนาด 255 ตัวอักษรขึ้นไปจะเพียงพอ
  • ประเภทของ field: ใช้ประเภทข้อมูล VARCHAR หรือ TEXT สำหรับ field ที่เก็บ hash

ตัวอย่าง (MySQL):

CREATE TABLE users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(255) NOT NULL,
    email VARCHAR(100) NOT NULL
);

ตัวอย่างการ insert ข้อมูลด้วย PDO:

<?php

try {
    $pdo = new PDO("mysql:host=localhost;dbname=mydatabase", "username", "password");
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $username = "john.doe";
    $password = "mySecretPassword123";
    $email = "john.doe@example.com";

    // Hash รหัสผ่าน
    $hashedPassword = password_hash($password, PASSWORD_DEFAULT);

    // เตรียม prepared statement
    $stmt = $pdo->prepare("INSERT INTO users (username, password, email) VALUES (:username, :password, :email)");

    // Bind parameters
    $stmt->bindParam(":username", $username);
    $stmt->bindParam(":password", $hashedPassword);
    $stmt->bindParam(":email", $email);

    // Execute statement
    $stmt->execute();

    echo "User added successfully!";

} catch (PDOException $e) {
    echo "Error: " . $e->getMessage();
}

?>

ข้อผิดพลาดที่พบบ่อย

  • ลืม hash รหัสผ่าน: ข้อผิดพลาดที่พบบ่อยที่สุดคือการพยายามเก็บรหัสผ่านแบบ plaintext ในฐานข้อมูล
  • ขนาด field ไม่เพียงพอ: ตรวจสอบให้แน่ใจว่า field ที่เก็บ hash มีขนาดเพียงพอ (อย่างน้อย 255 ตัวอักษร)
  • ใช้ algorithm ที่ไม่ปลอดภัย: หลีกเลี่ยงการใช้ MD5 หรือ SHA1 และเลือกใช้ bcrypt หรือ Argon2i แทน
  • ไม่จัดการ exception: ควรใช้ try-catch block เพื่อจัดการ exception ที่อาจเกิดขึ้นระหว่างการเชื่อมต่อฐานข้อมูลและการ execute query

สรุป

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

Office.in.th Custom Service

この構成をもとにシステムを開発・カスタマイズしたいですか?

Office.in.th は、エンタープライズ Web アプリケーション、API 連携、官民の業務管理システムの設計・開発を承り、長期的なサポートも提供します。

ソフトウェア開発サービスを見る