قواعد الأمان الأساسية

تتيح لك Firebase Security Rules التحكّم في الوصول إلى بياناتك المخزّنة. تعني بنية قواعد المرنة أنّه يمكنك إنشاء قواعد تتطابق مع أي شيء، بدءًا من جميع عمليات الكتابة في قاعدة البيانات بالكامل إلى العمليات التي يتم إجراؤها على مستند معيّن.

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

للوصول إلى القواعد وتعديلها، اتّبِع الخطوات الموضّحة في مقالة إدارة Firebase Security Rules ونشره.

القواعد التلقائية: وضع القفل

عند إنشاء مثيل قاعدة بيانات أو مساحة تخزين في وحدة تحكّم Firebase، يمكنك اختيار ما إذا كان Firebase Security Rules سيحظر الوصول إلى بياناتك (الوضع المُقفَل) أو سيسمح لأي مستخدم بالوصول إليها (الوضع التجريبي). في Cloud Firestore و Realtime Database، تمنع القواعد التلقائية للوضع المُقفَل الوصول إلى جميع المستخدمين. في Cloud Storage، يمكن فقط للمستخدمين الذين تم إثبات هويتهم الوصول إلى حِزم التخزين.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": false,
    ".write": false
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

قواعد بيئة التطوير

أثناء العمل على تطبيقك، قد تحتاج إلى إذن بالوصول إلى بياناتك بشكل مفتوح نسبيًا أو غير مقيد. احرص على تحديث Rules قبل نشر التطبيق في قناة الإصدار العلني. يُرجى العلم أيضًا أنّه في حال نشر تطبيقك، سيصبح متاحًا للجميع، حتى إذا لم يسبق لك إطلاقه.

تذكَّر أنّ Firebase تسمح للعملاء بالوصول المباشر إلى بياناتك، وتعدّ Firebase Security Rules هي الإجراء الوقائي الوحيد الذي يحظر وصول المستخدمين الضارّين. هناك العديد من المزايا لتحديد القواعد بشكل منفصل عن منطق المنتج، فالعملاء ليسوا مسؤولين عن فرض الأمان ولن تؤدي عمليات تنفيذ الأخطاء إلى تعريض بياناتك للخطر، والأهم من ذلك، عدم الاعتماد على خادم وسيط لحماية البيانات من العالم.

جميع المستخدمين الذين تمّت مصادقتهم

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

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Realtime Database

{
  "rules": {
    ".read": "auth.uid !== null",
    ".write": "auth.uid !== null"
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

القواعد الجاهزة للإصدار العلني

أثناء الاستعداد لنشر تطبيقك، يُرجى التأكّد من حماية بياناتك ومنح المستخدمين إمكانية الوصول بشكل صحيح. يمكنك الاستفادة من Authentication لإعداد إذن الوصول المستنِد إلى المستخدمين والقراءة مباشرةً من قاعدة بياناتك لإعداد إذن الوصول المستنِد إلى البيانات.

ننصحك بكتابة القواعد أثناء تنظيم بياناتك، لأنّ طريقة إعداد قواعدك تؤثّر في كيفية تقييد الوصول إلى البيانات في مسارات مختلفة.

إذن وصول لمالك المحتوى فقط

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

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

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

لإعداد هذه القاعدة: أنشئ قاعدة تؤكّد أنّ المستخدم الذي يطلب الوصول لقراءة البيانات أو كتابتها هو المستخدم الذي يملك هذه البيانات.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{documents=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

أذونات وصول مختلطة عامة وخاصة

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

حالات تطبيق هذه القاعدة: تعمل هذه القاعدة بشكل جيد مع التطبيقات التي تتطلّب عناصر قابلة للقراءة بشكل علني، ولكن يجب حصر إذن التعديل على مالكي هذه العناصر. على سبيل المثال، تطبيق محادثة أو مدونة.

حالات عدم تطبيق هذه القاعدة: مثل قاعدة "مالك المحتوى فقط"، لا تعمل مجموعة القواعد هذه عندما يحتاج عدة مستخدمين إلى تعديل البيانات نفسها. سيؤدي ذلك إلى استبدال بيانات المستخدمين ببيانات بعضهم البعض في النهاية.

لإعداد هذه القاعدة: يمكنك إنشاء قاعدة تتيح إمكانية الوصول للقراءة لجميع المستخدمين (أو جميع المستخدمين الذين تمت مصادقتهم) والتأكّد من أنّ المستخدم هو مالك البيانات التي يكتبها.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}

Realtime Database

{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data

  "rules": {
    "some_path": {
      "$uid": {
        ".read": true,
        // or ".read": "auth.uid !== null" for only authenticated users
        ".write": "auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/path/to/file.txt"
    match /user/{userId}/{allPaths=**} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

الوصول المستنِد إلى السمات والوصول المستنِد إلى الدور

لكي تعمل هذه القواعد، عليك تحديد سمات للمستخدمين في بياناتك وتحديدها لهم. Firebase Security Rules التحقّق من الطلب مقارنةً بالبيانات الواردة من قاعدة البيانات أو metadata الملف لتأكيد الوصول أو رفضه

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

في حال عدم نجاح هذه القاعدة: في Realtime Database وCloud Storage، لا يمكن لقواعدك الاستفادة من طريقة get() التي يمكن أن تتضمّنها قواعد Cloud Firestore. وبالتالي، يجب عليك هيكلة قاعدة البيانات أو بيانات التعريف للملف لتعكس السمات التي تستخدمها في قواعدك.

لإعداد هذه القاعدة: في Cloud Firestore، أدرِج حقلًا في ملفّات المستخدمين يمكنك قراءته، ثمّ وضِّح قاعدتك لقراءة هذا الحقل ومنح إذن الوصول بشكل مشروط. في Realtime Database، أنشئ مسار بيانات يحدد مستخدمي تطبيقك ويمنحهم دورًا في عقدة فرعية.

يمكنك أيضًا إعداد مطالبات مخصّصة في Authentication ثم استرداد هذه المعلومات من المتغيّر auth.token في أيّ Firebase Security Rules.

السمات والأدوار المحدّدة بالبيانات

لا تعمل هذه القواعد إلا في Cloud Firestore وRealtime Database.

Cloud Firestore

تذكَّر أنّه في أي وقت تتضمّن فيه قواعدك عملية قراءة، مثل القواعد أدناه، يتم تحصيل رسوم منك مقابل عملية قراءة في Cloud Firestore.

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "${subpath}": {
        //
        ".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
        ".read": true
      }
    }
  }
}

سمات المطالبات المخصّصة والأدوار

لتنفيذ هذه القواعد، عليك إعداد مطالبات مخصّصة في Firebase Authentication ثم الاستفادة من المطالبات في قواعدك.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an admin claim
    allow write: if request.auth.token.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if request.auth.token.reader == "true";
     allow write: if request.auth.token.writer == "true";
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Create a custom claim for each role or group
        // you want to leverage
        ".write": "auth.uid !== null && auth.token.writer === true",
        ".read": "auth.uid !== null && auth.token.reader === true"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Allow reads if the group ID in your token matches the file metadata's `owner` property
  // Allow writes if the group ID is in the user's custom token
  match /files/{groupId}/{fileName} {
    allow read: if resource.metadata.owner == request.auth.token.groupId;
    allow write: if request.auth.token.groupId == groupId;
  }
}

سمات المستأجر

لتنفيذ هذه القواعد، عليك إعداد ميزة استئجار مساحات متعددة في Google Cloud Identity Platform ‏ (GCIP)، ثم الاستفادة من المستأجر في قواعدك. تسمح الأمثلة التالية بالكتابة من مستخدم في مستأجر معيّن، مثل tenant2-m6tyz.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For tenant-based access control, check for a tenantID
    allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
    allow read: true;
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Only allow reads and writes if user belongs to a specific tenant
        ".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
        ".read": "auth.uid !== null
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Only allow reads and writes if user belongs to a specific tenant
  match /files/{tenantId}/{fileName} {
    allow read: if request.auth != null;
    allow write: if request.auth.token.firebase.tenant == tenantId;
  }
}