Database User Management ใน MySQL

การจัดการ User เป็นหัวใจสำคัญของการรักษาความปลอดภัยฐานข้อมูล เพราะทุกการเข้าถึงข้อมูลต้องผ่านระบบ Authentication และ Authorization ที่กำหนดไว้ หากจัดการ User ไม่ดี อาจเกิดปัญหาตั้งแต่ข้อมูลรั่วไหลไปจนถึงถูกลบข้อมูลทั้งหมดโดยไม่ตั้งใจ

บทความนี้จะอธิบายการจัดการ User ในระบบจัดการฐานข้อมูล MySQL อย่างครบถ้วน ตั้งแต่การสร้าง User, กำหนดสิทธิ์ (Privileges), เปลี่ยนรหัสผ่าน, ตรวจสอบสิทธิ์ ไปจนถึงการลบ User และแนวทาง Best Practices สำหรับระบบ Production

ทำความเข้าใจระบบ Authentication

MySQL ใช้ระบบ Authentication ที่ระบุตัวตนผู้ใช้ด้วยชื่อ User + Host รวมกัน หมายความว่า ‘admin’@’localhost’ กับ ‘admin’@’192.168.1.100’ เป็นคนละ User กัน แม้ชื่อจะเหมือนกันก็ตาม รูปแบบนี้ช่วยให้ควบคุมได้ว่า User แต่ละคนเข้าถึงได้จากเครื่องไหนบ้าง

ตั้งแต่เวอร์ชัน 8.0 เป็นต้นมา ระบบ Authentication Plugin เปลี่ยนจาก mysql_native_password เป็น caching_sha2_password ซึ่งปลอดภัยกว่า แต่ Application เก่าบางตัวอาจไม่รองรับ ต้องระบุ Plugin ตอนสร้าง User หากต้องการใช้แบบเดิม

สร้าง User ใหม่

ใช้คำสั่ง CREATE USER เพื่อสร้าง User ใหม่พร้อมกำหนดรหัสผ่าน

CREATE USER 'developer'@'localhost' IDENTIFIED BY 'Dev$ecure2024!';
CREATE USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'W3bApp!Str0ng';
CREATE USER 'analyst'@'%' IDENTIFIED BY 'An@lyst#2024!';

ตัวอย่างแรกสร้าง User ที่เข้าถึงได้เฉพาะจาก localhost ตัวที่สองเข้าได้จาก IP ในวง 192.168.1.x และตัวที่สามเข้าได้จากทุก IP (ใช้ ‘%’ แทน) ควรจำกัด Host ให้แคบที่สุดเท่าที่เป็นไปได้

หากต้องการสร้าง User ที่ใช้ Authentication Plugin แบบเดิมสำหรับ Application ที่ยังไม่รองรับ caching_sha2_password

CREATE USER 'legacy_app'@'localhost' IDENTIFIED WITH mysql_native_password BY 'L3gacy!Pass';

ระบบ Privileges

Privileges กำหนดว่า User ทำอะไรได้บ้าง แบ่งเป็นหลายระดับตั้งแต่ Global (ทั้งเซิร์ฟเวอร์), Database, Table ไปจนถึง Column Level สิทธิ์ที่ใช้บ่อยได้แก่ SELECT (อ่านข้อมูล), INSERT (เพิ่มข้อมูล), UPDATE (แก้ไขข้อมูล), DELETE (ลบข้อมูล), CREATE (สร้างตารางหรือฐานข้อมูล), DROP (ลบตารางหรือฐานข้อมูล), ALTER (แก้โครงสร้างตาราง) และ GRANT OPTION (มอบสิทธิ์ให้ User อื่นได้)

กำหนดสิทธิ์ด้วย GRANT

ใช้คำสั่ง GRANT เพื่อมอบสิทธิ์ให้ User โดยระบุสิทธิ์ที่ต้องการ ฐานข้อมูล และตารางที่อนุญาต

GRANT SELECT, INSERT, UPDATE, DELETE ON myapp_db.* TO 'webapp'@'192.168.1.%';

GRANT SELECT ON myapp_db.* TO 'analyst'@'%';

GRANT ALL PRIVILEGES ON dev_db.* TO 'developer'@'localhost';

FLUSH PRIVILEGES;

คำสั่งแรกให้สิทธิ์ CRUD (Create, Read, Update, Delete) บนทุกตารางในฐานข้อมูล myapp_db คำสั่งที่สองให้สิทธิ์อ่านอย่างเดียว และคำสั่งที่สามให้สิทธิ์ทั้งหมดบนฐานข้อมูล dev_db คำสั่ง FLUSH PRIVILEGES ทำให้การเปลี่ยนแปลงมีผลทันที

กำหนดสิทธิ์ระดับ Table และ Column

สามารถจำกัดสิทธิ์ให้ละเอียดถึงระดับตารางหรือคอลัมน์ได้

GRANT SELECT, INSERT ON myapp_db.orders TO 'webapp'@'192.168.1.%';

GRANT SELECT (id, name, email) ON myapp_db.customers TO 'analyst'@'%';

คำสั่งแรกให้สิทธิ์อ่านและเพิ่มข้อมูลเฉพาะตาราง orders ส่วนคำสั่งที่สองให้อ่านได้เฉพาะ 3 คอลัมน์ในตาราง customers เหมาะกับกรณีที่ต้องปกป้องข้อมูลละเอียดอ่อนเช่น เบอร์โทร หรือที่อยู่

ตรวจสอบสิทธิ์ของ User

ใช้คำสั่ง SHOW GRANTS เพื่อดูสิทธิ์ทั้งหมดของ User

SHOW GRANTS FOR 'webapp'@'192.168.1.%';

SHOW GRANTS FOR CURRENT_USER();

คำสั่งแรกแสดงสิทธิ์ของ User ที่ระบุ ส่วนคำสั่งที่สองแสดงสิทธิ์ของ User ที่กำลัง Login อยู่ ควรตรวจสอบสิทธิ์เป็นประจำเพื่อให้แน่ใจว่าไม่มี User ที่ได้สิทธิ์เกินจำเป็น

ถอนสิทธิ์ด้วย REVOKE

หากต้องการลดสิทธิ์ของ User ให้ใช้คำสั่ง REVOKE

REVOKE INSERT, UPDATE, DELETE ON myapp_db.* FROM 'analyst'@'%';

REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'developer'@'localhost';

FLUSH PRIVILEGES;

คำสั่งแรกถอนสิทธิ์เขียนออกจาก analyst เหลือเฉพาะ SELECT ส่วนคำสั่งที่สองถอนสิทธิ์ทั้งหมดของ developer ออก

เปลี่ยนรหัสผ่าน

ใช้คำสั่ง ALTER USER เพื่อเปลี่ยนรหัสผ่าน

ALTER USER 'webapp'@'192.168.1.%' IDENTIFIED BY 'NewStr0ng!Pass2024';

ALTER USER USER() IDENTIFIED BY 'MyN3w!Password';

คำสั่งแรกเปลี่ยนรหัสผ่านของ User ที่ระบุ (ต้องมีสิทธิ์ ALTER USER) ส่วนคำสั่งที่สองเปลี่ยนรหัสผ่านของตัวเอง ควรเปลี่ยนรหัสผ่านเป็นประจำอย่างน้อยทุก 90 วัน

ตั้งค่าหมดอายุรหัสผ่าน

กำหนดให้รหัสผ่านหมดอายุอัตโนมัติเพื่อบังคับให้เปลี่ยนรหัสผ่านตามรอบ

ALTER USER 'webapp'@'192.168.1.%' PASSWORD EXPIRE INTERVAL 90 DAY;

ALTER USER 'developer'@'localhost' PASSWORD EXPIRE;

คำสั่งแรกตั้งให้รหัสผ่านหมดอายุทุก 90 วัน ส่วนคำสั่งที่สองบังคับให้หมดอายุทันที (User ต้องเปลี่ยนรหัสผ่านใหม่ก่อนทำอย่างอื่น) สามารถตั้ง Default Password Expiration สำหรับทุก User ได้ใน Configuration File

[mysqld]
default_password_lifetime = 90

จำกัด Resource ของ User

ป้องกันไม่ให้ User บางคนใช้ Resource มากเกินไปจนกระทบ User อื่น

ALTER USER 'analyst'@'%'
  WITH MAX_QUERIES_PER_HOUR 1000
  MAX_UPDATES_PER_HOUR 100
  MAX_CONNECTIONS_PER_HOUR 50
  MAX_USER_CONNECTIONS 5;

MAX_QUERIES_PER_HOUR จำกัด Query ต่อชั่วโมง, MAX_UPDATES_PER_HOUR จำกัดคำสั่งเขียน, MAX_CONNECTIONS_PER_HOUR จำกัดจำนวนครั้งที่ Connect ต่อชั่วโมง และ MAX_USER_CONNECTIONS จำกัดจำนวน Connection พร้อมกัน

ล็อคและปลดล็อค User

หากต้องการระงับ User ชั่วคราวโดยไม่ลบออก สามารถล็อค Account ได้

ALTER USER 'developer'@'localhost' ACCOUNT LOCK;

ALTER USER 'developer'@'localhost' ACCOUNT UNLOCK;

User ที่ถูกล็อคจะไม่สามารถ Login ได้ แต่สิทธิ์และการตั้งค่าทั้งหมดยังคงอยู่ เหมาะกับกรณีที่พนักงานลาออกชั่วคราว หรือพบพฤติกรรมที่น่าสงสัยและต้องการตรวจสอบก่อน

ลบ User

เมื่อไม่ต้องการ User อีกต่อไป ให้ลบออกด้วย DROP USER

DROP USER 'legacy_app'@'localhost';

DROP USER IF EXISTS 'temp_user'@'%';

คำสั่ง DROP USER จะลบทั้ง User และสิทธิ์ทั้งหมดออก การใช้ IF EXISTS ช่วยป้องกัน Error หาก User ไม่มีอยู่แล้ว

ดูรายชื่อ User ทั้งหมด

ตรวจสอบ User ทั้งหมดในระบบด้วย Query จากตาราง mysql.user

SELECT user, host, account_locked, password_expired,
       password_lifetime, plugin
FROM mysql.user
ORDER BY user;

Query นี้แสดงชื่อ User, Host ที่อนุญาต, สถานะล็อค, สถานะหมดอายุรหัสผ่าน, อายุรหัสผ่าน และ Authentication Plugin ที่ใช้ ควรรัน Query นี้เป็นประจำเพื่อตรวจสอบว่าไม่มี User ที่ไม่จำเป็นหลงเหลืออยู่

Role-Based Access Control

ตั้งแต่เวอร์ชัน 8.0 รองรับ Role ที่ช่วยจัดกลุ่มสิทธิ์ให้จัดการง่ายขึ้น แทนที่จะ GRANT สิทธิ์ให้ User ทีละคน สามารถสร้าง Role แล้วมอบ Role ให้ User ได้

CREATE ROLE 'app_read', 'app_write', 'app_admin';

GRANT SELECT ON myapp_db.* TO 'app_read';
GRANT INSERT, UPDATE, DELETE ON myapp_db.* TO 'app_write';
GRANT ALL PRIVILEGES ON myapp_db.* TO 'app_admin';

GRANT 'app_read', 'app_write' TO 'webapp'@'192.168.1.%';
GRANT 'app_read' TO 'analyst'@'%';
GRANT 'app_admin' TO 'developer'@'localhost';

User ต้อง Activate Role หลัง Login ด้วยคำสั่ง SET ROLE หรือตั้ง Default Role ให้ Active อัตโนมัติ

SET DEFAULT ROLE 'app_read', 'app_write' TO 'webapp'@'192.168.1.%';
SET DEFAULT ROLE ALL TO 'developer'@'localhost';

เมื่อต้องเปลี่ยนสิทธิ์ทั้งกลุ่ม เพียงแก้ไขสิทธิ์ที่ Role ทุก User ที่ได้รับ Role นั้นจะได้รับผลกระทบพร้อมกัน ช่วยลดความผิดพลาดและความซ้ำซ้อนในการจัดการสิทธิ์

Best Practices สำหรับ Production

ใช้หลัก Least Privilege — ให้สิทธิ์เท่าที่จำเป็นเท่านั้น Application ที่ต้องแค่อ่านเขียนข้อมูลไม่ควรมีสิทธิ์ DROP หรือ ALTER ถ้าเกิดช่องโหว่ในแอป ความเสียหายจะจำกัดอยู่ในขอบเขตที่ User นั้นทำได้

แยก User ตามหน้าที่ — สร้าง User แยกสำหรับแต่ละ Application และแต่ละหน้าที่ เช่น User สำหรับ Web Application, User สำหรับ Backup (สิทธิ์ SELECT + LOCK TABLES), User สำหรับ Monitoring (สิทธิ์ PROCESS + REPLICATION CLIENT) อย่าใช้ User เดียวกันทุกงาน

ห้ามใช้ Root สำหรับ Application — Root ควรใช้สำหรับงานบริหารระบบเท่านั้น อย่าเอา Root Credential ไปใส่ใน Application Config เด็ดขาด

จำกัด Host ให้แคบที่สุด — ใช้ ‘localhost’ สำหรับ Application ที่รันบนเครื่องเดียวกัน หลีกเลี่ยงการใช้ ‘%’ (ทุก IP) ยกเว้นจำเป็นจริง ๆ และควรใช้ร่วมกับ Firewall

ตรวจสอบสิทธิ์เป็นประจำ — รัน Audit Query เดือนละครั้งเพื่อตรวจสอบ User ที่ไม่ได้ใช้งาน, สิทธิ์ที่มากเกินไป หรือ User ที่ไม่ได้ล็อคทั้งที่ควรล็อค

สรุป

การจัดการ User เป็นส่วนสำคัญของการรักษาความปลอดภัยฐานข้อมูล สิ่งสำคัญที่ต้องจำ ได้แก่ ระบบ Authentication ใช้ User+Host ร่วมกัน, ใช้ GRANT ให้สิทธิ์เท่าที่จำเป็น, ใช้ REVOKE ถอนสิทธิ์ที่ไม่ต้องการ, ตั้ง Password Expiration, ใช้ Role จัดกลุ่มสิทธิ์ให้จัดการง่าย และตรวจสอบสิทธิ์เป็นประจำ เมื่อทำตามแนวทางเหล่านี้ ระบบจัดการฐานข้อมูลจะมีความปลอดภัยและจัดการได้อย่างเป็นระบบ

แนะนำบริการ DE

หากต้องการเซิร์ฟเวอร์ที่ติดตั้งและจัดการระบบฐานข้อมูลได้อย่างอิสระพร้อม Root Access เต็มรูปแบบ Cloud VPS ของ DE เหมาะสำหรับทีมที่ต้องการควบคุมการตั้งค่า User, สิทธิ์ และ Security Policy ได้ทุกรายละเอียด

สำหรับผู้ที่ต้องการฐานข้อมูลพร้อมใช้งานโดยไม่ต้องจัดการ User และสิทธิ์ในระดับลึก Cloud Hosting ของ DE มาพร้อมระบบจัดการฐานข้อมูลและ phpMyAdmin ที่ตั้งค่าให้เรียบร้อย เหมาะกับเว็บแอปพลิเคชันทั่วไป