تخطَّ إلى المحتوى

المستخدمون والصلاحيات والنسخ الاحتياطي في MySQL

الدرس 12 من 12 · MySQL

حتى الآن تعمل بالمستخدم root، وهو يملك كل شيء: يحذف أي جدول وأي قاعدة. هذا مقبول على جهازك، وخطير على خادم حقيقي: لو تسربت كلمة مروره من كود الموقع، ضاع كل شيء. في هذا الدرس الأخير ستتعلم مهارتين يحتاجهما كل من ينشر موقعاً: منح كل برنامج أقل صلاحيات تكفيه، وأخذ نسخة احتياطية تعيد بها بياناتك إذا وقعت الكارثة.

SELECT user, host FROM mysql.user ORDER BY user;

الناتج:

user host
mysql.infoschema localhost
mysql.session localhost
mysql.sys localhost
root localhost

الحساب في MySQL اسم ومصدر اتصال معاً: root@localhost يعني المستخدم root عندما يتصل من الجهاز نفسه. والحسابات التي تبدأ بـ mysql. داخلية للنظام، فلا تلمسها.

سننشئ حساباً خاصاً بتطبيق المتجر:

CREATE USER 'shop_app'@'localhost' IDENTIFIED BY 'Str0ng!Pass2026';
SHOW GRANTS FOR 'shop_app'@'localhost';

الناتج:

Grants for shop_app@localhost
GRANT USAGE ON *.* TO `shop_app`@`localhost`

USAGE تعني «يستطيع تسجيل الدخول فقط»: لا صلاحية على أي بيانات. جرّبنا الدخول بالحساب الجديد:

نافذة طرفيّة
mysql -u shop_app -p
USE shop;

الناتج: ERROR 1044 (42000): Access denied for user 'shop_app'@'localhost' to database 'shop'

المستخدم الجديد لا يرى قاعدة shop أصلاً. هذا هو المبدأ الصحيح: كل شيء ممنوع حتى تسمح به.

التطبيق يحتاج قراءة البيانات وإضافة الطلبات وتعديل المخزون، ولا يحتاج حذف الجداول أبداً. من حساب root:

GRANT SELECT, INSERT, UPDATE ON shop.* TO 'shop_app'@'localhost';
SHOW GRANTS FOR 'shop_app'@'localhost';

الناتج:

Grants for shop_app@localhost
GRANT USAGE ON *.* TO `shop_app`@`localhost`
GRANT SELECT, INSERT, UPDATE ON `shop`.* TO `shop_app`@`localhost`
  • بعد GRANT: الصلاحيات الممنوحة.
  • ON shop.*: على كل جداول قاعدة shop. ويمكن التحديد أكثر: shop.products لجدول واحد.
  • TO: الحساب المستفيد.

والآن بحساب shop_app:

SELECT COUNT(*) AS products_count FROM products;

الناتج:

products_count
6
DELETE FROM orders WHERE id = 1;

الناتج: ERROR 1142 (42000): DELETE command denied to user 'shop_app'@'localhost' for table 'orders'

القراءة تعمل، والحذف مرفوض. حتى لو اخترق أحدهم الموقع وحصل على كلمة مرور shop_app، لن يستطيع حذف الطلبات ولا إسقاط الجداول.

هذا هو مبدأ أقل الصلاحيات (Least Privilege). مثل مفاتيح الفندق: مفتاح النزيل يفتح غرفته فقط، ومفتاح عامل النظافة يفتح الغرف ولا يفتح الخزنة، والمفتاح الرئيسي مع المدير وحده.

الصلاحية تسمح بـ
SELECT قراءة البيانات
INSERT و UPDATE و DELETE إضافة الصفوف وتعديلها وحذفها
CREATE و ALTER و DROP إنشاء الجداول وتعديل بنيتها وحذفها
ALL PRIVILEGES كل ما سبق. لا تمنحها لتطبيق

في الدرس السابق أنشأنا العرض order_details. سنمنح موظف التقارير حق القراءة منه وحده:

CREATE USER 'reports'@'localhost' IDENTIFIED BY 'R3ports!Only';
GRANT SELECT ON shop.order_details TO 'reports'@'localhost';

وبحساب reports:

SHOW TABLES;

الناتج:

Tables_in_shop
order_details
SELECT * FROM customers;

الناتج: ERROR 1142 (42000): SELECT command denied to user 'reports'@'localhost' for table 'customers'

يرى تقرير الطلبات كاملاً، ولا يرى جدول العملاء ولا يعلم بوجود بقية الجداول.

REVOKE UPDATE ON shop.* FROM 'shop_app'@'localhost';
SHOW GRANTS FOR 'shop_app'@'localhost';

الناتج:

Grants for shop_app@localhost
GRANT USAGE ON *.* TO `shop_app`@`localhost`
GRANT SELECT, INSERT ON `shop`.* TO `shop_app`@`localhost`

REVOKE عكس GRANT بالصيغة نفسها، مع FROM بدل TO. بعدها أي UPDATE من هذا الحساب يُرفض بالخطأ 1142.

تغيير كلمة المرور وحذف المستخدم

Section titled “تغيير كلمة المرور وحذف المستخدم”
ALTER USER 'shop_app'@'localhost' IDENTIFIED BY 'N3w!Pass2027';
DROP USER 'reports'@'localhost';

بعد ALTER USER تُرفض الكلمة القديمة فوراً:

الناتج: ERROR 1045 (28000): Access denied for user 'shop_app'@'localhost' (using password: YES)

وهذه هي الرسالة نفسها التي تظهر عند أي كلمة مرور خاطئة أو حساب محذوف. MySQL لا تخبرك أيهما الخطأ، حتى لا تساعد المتسللين.

القرص يتلف، و DELETE بلا WHERE يحدث، والخادم يُخترق. النسخة الاحتياطية هي الفرق بين «يوم سيئ» و«نهاية المشروع». الأداة mysqldump تأتي مع MySQL وتُشغَّل من الطرفية لا من داخل mysql:

نافذة طرفيّة
mysqldump -u root -p shop > shop_backup.sql

الناتج ملف نصي عادي فيه أوامر SQL تعيد بناء القاعدة كلها. افتحه بأي محرر وستجد شيئاً كهذا:

-- MySQL dump 10.13 Distrib 8.4.11, for Win64 (x86_64)
CREATE TABLE `customers` (
...
);
INSERT INTO `customers` VALUES (1,'سارة','القاهرة'),(2,'عمر','الإسكندرية'),(4,'كريم','القاهرة');

لكل جدول أمر CREATE TABLE ثم INSERT ببياناته، وفي آخر الملف تعريفات العروض. ولنسخ جداول محددة فقط اكتب أسماءها بعد اسم القاعدة: mysqldump -u root -p shop products customers > two_tables.sql.

للاستعادة تنفّذ أوامر الملف على قاعدة فارغة. من داخل mysql:

CREATE DATABASE shop_copy CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

ثم من الطرفية:

نافذة طرفيّة
mysql -u root -p shop_copy < shop_backup.sql

وللتأكد:

USE shop_copy;
SHOW FULL TABLES;

الناتج:

Tables_in_shop_copy Table_type
customers BASE TABLE
order_details VIEW
orders BASE TABLE
product_status VIEW
products BASE TABLE
subscribers BASE TABLE

عادت الجداول الأربعة والعرضان، والمنتجات الستة والعملاء الثلاثة كما هم.

  1. أنشئ مستخدماً viewer بكلمة مرور قوية، وامنحه SELECT فقط على shop.products.
  2. ادخل بحسابه وجرّب قراءة المنتجات، ثم جرّب تعديل سعر، ولاحظ رسالة الخطأ.
  3. خذ نسخة احتياطية من قاعدة shop، وافتح الملف في محرر النصوص واقرأ محتواه.
  4. تحدٍّ: أنشئ قاعدة shop_test، واستعد النسخة فيها، ثم احذف منتجاً من shop_test وتأكد أن shop الأصلية لم تتأثر.
  • استخدام root في التطبيق: أي ثغرة في الموقع تصبح سيطرة كاملة على الخادم. أنشئ حساباً محدود الصلاحيات لكل تطبيق.
  • GRANT ALL للسهولة: تمنح الحذف وتعديل البنية دون حاجة. امنح ما يحتاجه التطبيق فقط.
  • كلمة المرور في سطر الأمر: كتابة -pPassword تحفظها في سجل الطرفية. اكتب -p وحدها وأدخل الكلمة عند السؤال.
  • نسخ احتياطية على الخادم نفسه: إذا تلف القرص ضاعت القاعدة ونسختها معاً.

سؤال

تطبيق موقع يعرض المنتجات ويسجّل الطلبات. ما أنسب صلاحيات لحسابه؟

سؤال

ماذا يحتوي الملف الناتج عن mysqldump؟

  • الحساب في MySQL اسم ومصدر اتصال: 'user'@'host'، والحساب الجديد بلا صلاحيات.
  • GRANT صلاحيات ON قاعدة.جدول TO حساب تمنح، و REVOKE ... FROM تسحب.
  • امنح كل تطبيق أقل صلاحيات تكفيه، ولا تستخدم root في كود موقعك.
  • mysqldump تنسخ القاعدة إلى ملف SQL، والاستعادة بتنفيذ الملف على قاعدة فارغة.
  • مبروك! أنهيت كورس MySQL: من أول جدول إلى الفهارس والعروض والصلاحيات والنسخ الاحتياطي.