ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

การ Audit Log

บทความนี้กล่าวถึง Audit Log ซึ่งเป็นเครื่องมือสำคัญสำหรับการบันทึกการเปลี่ยนแปลงข้อมูลในฐานข้อมูล เพื่อใช้ตรวจสอบย้อนหลัง ปฏิบัติตามกฎหมาย และปรับปรุงระบบ โดยอธ...

การ Audit Log: บันทึกทุกการเปลี่ยนแปลงในฐานข้อมูล

ในบทที่แล้ว เราได้พูดถึง Two-Factor Authentication (2FA) เพื่อเพิ่มความปลอดภัยในการยืนยันตัวตนผู้ใช้งาน ในบทนี้ เราจะมาเรียนรู้เรื่อง Audit Log ซึ่งเป็นอีกหนึ่งเครื่องมือสำคัญในการรักษาความปลอดภัยและการตรวจสอบระบบของเรา Audit Log คือบันทึกการเปลี่ยนแปลงข้อมูลที่เกิดขึ้นในฐานข้อมูล ช่วยให้เราสามารถติดตามได้ว่าใคร ทำอะไร เมื่อไหร่ และที่ไหน การมี Audit Log ที่ดีจะช่วยให้เรา:

  • ตรวจสอบย้อนหลัง: เมื่อเกิดปัญหา เช่น ข้อมูลถูกแก้ไขหรือลบโดยไม่ได้รับอนุญาต เราสามารถใช้ Audit Log เพื่อตรวจสอบหาสาเหตุและผู้กระทำ
  • ปฏิบัติตามกฎหมายและข้อบังคับ: ในหลายอุตสาหกรรม มีข้อกำหนดทางกฎหมายให้ต้องมีการบันทึกการเปลี่ยนแปลงข้อมูลเพื่อการตรวจสอบ
  • ปรับปรุงระบบ: การวิเคราะห์ Audit Log สามารถช่วยให้เราเข้าใจพฤติกรรมการใช้งานระบบและนำไปปรับปรุงให้ดีขึ้น

การสร้าง Audit Log Table

ขั้นตอนแรกในการใช้งาน Audit Log คือการสร้างตารางสำหรับเก็บข้อมูลการเปลี่ยนแปลง นี่คือตัวอย่างโครงสร้างตาราง Audit Log ใน MySQL:

CREATE TABLE audit_log (
    id INT AUTO_INCREMENT PRIMARY KEY,
    user_id INT,
    action VARCHAR(255) NOT NULL,
    table_name VARCHAR(255) NOT NULL,
    record_id INT,
    old_value TEXT,
    new_value TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

คำอธิบายแต่ละฟิลด์:

  • id: Primary key ของตาราง Audit Log
  • user_id: ID ของผู้ใช้ที่ทำการเปลี่ยนแปลง (Foreign Key อ้างอิงตาราง users)
  • action: ประเภทของการกระทำ (เช่น 'CREATE', 'UPDATE', 'DELETE')
  • table_name: ชื่อตารางที่เกิดการเปลี่ยนแปลง
  • record_id: ID ของ record ที่ถูกเปลี่ยนแปลง
  • old_value: ค่าเดิมของข้อมูลก่อนการเปลี่ยนแปลง (เก็บเป็น JSON หรือ String)
  • new_value: ค่าใหม่ของข้อมูลหลังการเปลี่ยนแปลง (เก็บเป็น JSON หรือ String)
  • created_at: วันและเวลาที่เกิดการเปลี่ยนแปลง

เหตุผลเชิงออกแบบ:

  • การใช้ TEXT สำหรับ old_value และ new_value ช่วยให้เราสามารถเก็บข้อมูลขนาดใหญ่ได้ แต่ควรระวังเรื่อง performance หากมีการ query ข้อมูลจำนวนมาก
  • การเก็บ old_value และ new_value เป็น JSON ทำให้เราสามารถเก็บข้อมูลที่ซับซ้อนได้ง่าย แต่ต้องระวังเรื่องความเข้ากันได้ของข้อมูล
  • การใช้ TIMESTAMP DEFAULT CURRENT_TIMESTAMP ทำให้ระบบบันทึกเวลาที่เกิดการเปลี่ยนแปลงโดยอัตโนมัติ

การบันทึก User Action

เมื่อเรามีตาราง Audit Log แล้ว ขั้นตอนต่อไปคือการบันทึกการเปลี่ยนแปลงข้อมูลที่เกิดขึ้นในฐานข้อมูล นี่คือตัวอย่างการบันทึกการสร้าง, แก้ไข, และลบข้อมูล:

ตัวอย่าง: การบันทึกการสร้างข้อมูล (CREATE)

<?php
function createUser($pdo, $user_data) {
    try {
        $sql = "INSERT INTO users (username, email, password) VALUES (:username, :email, :password)";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([
            'username' => $user_data['username'],
            'email' => $user_data['email'],
            'password' => password_hash($user_data['password'], PASSWORD_DEFAULT)
        ]);

        $user_id = $pdo->lastInsertId();

        // บันทึก Audit Log
        $audit_sql = "INSERT INTO audit_log (user_id, action, table_name, record_id, new_value) VALUES (:user_id, :action, :table_name, :record_id, :new_value)";
        $audit_stmt = $pdo->prepare($audit_sql);
        $audit_stmt->execute([
            'user_id' => $_SESSION['user_id'], // สมมติว่ามี Session เก็บ user_id
            'action' => 'CREATE',
            'table_name' => 'users',
            'record_id' => $user_id,
            'new_value' => json_encode($user_data)
        ]);

        return $user_id;

    } catch (PDOException $e) {
        // จัดการ Error
        echo "Error: " . $e->getMessage();
        return false;
    }
}
?>

ตัวอย่าง: การบันทึกการแก้ไขข้อมูล (UPDATE)

<?php
function updateUser($pdo, $user_id, $user_data) {
    try {
        // ดึงข้อมูลเดิมก่อนแก้ไข
        $sql_select = "SELECT * FROM users WHERE id = :id";
        $stmt_select = $pdo->prepare($sql_select);
        $stmt_select->execute(['id' => $user_id]);
        $old_data = $stmt_select->fetch(PDO::FETCH_ASSOC);

        $sql = "UPDATE users SET username = :username, email = :email WHERE id = :id";
        $stmt = $pdo->prepare($sql);
        $stmt->execute([
            'username' => $user_data['username'],
            'email' => $user_data['email'],
            'id' => $user_id
        ]);

        // บันทึก Audit Log
        $audit_sql = "INSERT INTO audit_log (user_id, action, table_name, record_id, old_value, new_value) VALUES (:user_id, :action, :table_name, :record_id, :old_value, :new_value)";
        $audit_stmt = $pdo->prepare($audit_sql);
        $audit_stmt->execute([
            'user_id' => $_SESSION['user_id'], // สมมติว่ามี Session เก็บ user_id
            'action' => 'UPDATE',
            'table_name' => 'users',
            'record_id' => $user_id,
            'old_value' => json_encode($old_data),
            'new_value' => json_encode($user_data)
        ]);

        return true;

    } catch (PDOException $e) {
        // จัดการ Error
        echo "Error: " . $e->getMessage();
        return false;
    }
}
?>

ตัวอย่าง: การบันทึกการลบข้อมูล (DELETE)

<?php
function deleteUser($pdo, $user_id) {
    try {
        // ดึงข้อมูลเดิมก่อนลบ
        $sql_select = "SELECT * FROM users WHERE id = :id";
        $stmt_select = $pdo->prepare($sql_select);
        $stmt_select->execute(['id' => $user_id]);
        $old_data = $stmt_select->fetch(PDO::FETCH_ASSOC);

        $sql = "DELETE FROM users WHERE id = :id";
        $stmt = $pdo->prepare($sql);
        $stmt->execute(['id' => $user_id]);

        // บันทึก Audit Log
        $audit_sql = "INSERT INTO audit_log (user_id, action, table_name, record_id, old_value) VALUES (:user_id, :action, :table_name, :record_id, :old_value)";
        $audit_stmt = $pdo->prepare($audit_sql);
        $audit_stmt->execute([
            'user_id' => $_SESSION['user_id'], // สมมติว่ามี Session เก็บ user_id
            'action' => 'DELETE',
            'table_name' => 'users',
            'record_id' => $user_id,
            'old_value' => json_encode($old_data)
        ]);

        return true;

    } catch (PDOException $e) {
        // จัดการ Error
        echo "Error: " . $e->getMessage();
        return false;
    }
}
?>

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

  • อย่าลืมจัดการ Error อย่างเหมาะสมเมื่อบันทึก Audit Log
  • ควรบันทึก user_id จาก Session หรือ Authentication token เพื่อระบุผู้ใช้งานที่ทำการเปลี่ยนแปลง
  • การเก็บข้อมูล old_value และ new_value อาจทำให้ตาราง Audit Log มีขนาดใหญ่ได้ ควรพิจารณาการ archive ข้อมูลเก่า
  • การบันทึก Audit Log ทุกครั้งอาจทำให้ performance ลดลง ควรพิจารณาใช้ Asynchronous Task หรือ Queue เพื่อบันทึกข้อมูลใน background

การตรวจสอบ Audit Log

เมื่อเรามี Audit Log แล้ว เราสามารถใช้ SQL Query เพื่อตรวจสอบข้อมูลได้ ตัวอย่าง:

-- ดึงข้อมูล Audit Log ทั้งหมด
SELECT * FROM audit_log;

-- ดึงข้อมูล Audit Log ของผู้ใช้ ID 123
SELECT * FROM audit_log WHERE user_id = 123;

-- ดึงข้อมูล Audit Log ที่เกิดจากการแก้ไข (UPDATE) ตาราง users
SELECT * FROM audit_log WHERE action = 'UPDATE' AND table_name = 'users';

-- ดึงข้อมูล Audit Log ในช่วงเวลาที่กำหนด
SELECT * FROM audit_log WHERE created_at BETWEEN '2023-10-26 00:00:00' AND '2023-10-26 23:59:59';

แนวปฏิบัติที่ดี:

  • สร้างหน้าจอสำหรับแสดง Audit Log ให้ผู้ดูแลระบบสามารถตรวจสอบได้ง่าย
  • เพิ่มฟังก์ชันการค้นหาและกรองข้อมูลใน Audit Log
  • กำหนดสิทธิ์การเข้าถึง Audit Log อย่างเข้มงวด

Audit Log เป็นเครื่องมือที่สำคัญในการรักษาความปลอดภัยและการตรวจสอบระบบของเรา การออกแบบและใช้งาน Audit Log อย่างถูกต้องจะช่วยให้เราสามารถติดตามและแก้ไขปัญหาที่เกิดขึ้นได้อย่างมีประสิทธิภาพ ในบทต่อไป เราจะพูดถึงการ Backup and Restore Database เพื่อป้องกันข้อมูลสูญหาย

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์