قواعد الأمان ومصادقة Firebase

Firebase Security Rules توفّر إمكانية التحكّم في الوصول إلى البيانات والتحقّق من صحتها بتنسيق يتيح التعامل مع مستويات متعدّدة من التعقيد. لإنشاء أنظمة وصول مستندة إلى المستخدمين والأدوار تحافظ على أمان بيانات المستخدمين، استخدِم Firebase Authentication مع Firebase Security Rules.

تحديد هوية المستخدمين

تحدّد خدمة Authentication هوية المستخدمين الذين يطلبون الوصول إلى بياناتك وتوفّر هذه المعلومات كمتغيّر يمكنك الاستفادة منه في قواعدك. يحتوي المتغيّر auth على المعلومات التالية:

  • uid: رقم تعريف مستخدم فريد يتم تعيينه للمستخدم الذي يطلب الوصول.
  • token: خريطة للقيم التي تجمعها خدمة Authentication.

يحتوي المتغيّر auth.token على القيم التالية:

الحقل الوصف
email عنوان البريد الإلكتروني المرتبط بالحساب، إذا كان متوفّرًا
email_verified true إذا أكّد المستخدم أنّه يمكنه الوصول إلى عنوان email تؤكّد بعض الخدمات تلقائيًا عناوين البريد الإلكتروني التي تملكها.
phone_number رقم الهاتف المرتبط بالحساب، إذا كان متوفّرًا
name الاسم المعروض للمستخدم، إذا تم ضبطه
sub رقم تعريف المستخدم (UID) في Firebase وهو رقم تعريف فريد ضمن المشروع.
firebase.identities قاموس بجميع الهويات المرتبطة بحساب هذا المستخدم يمكن أن تكون مفاتيح القاموس أيًا مما يلي: email وphone وgoogle.com وfacebook.com وgithub.com وtwitter.com. وقيم القاموس هي مصفوفات من المعرّفات الفريدة لكل مقدّم هوية مرتبط بالحساب. على سبيل المثال، يحتوي auth.token.firebase.identities["google.com"][0] على أول رقم تعريف مستخدم على Google مرتبط بالحساب.
firebase.sign_in_provider مقدّم خدمة تسجيل الدخول المستخدَم للحصول على هذا الرمز يمكن أن يكون أحد السلاسل التالية: custom أو password أو phone أو anonymous أو google.com أو facebook.com أو github.com أو twitter.com.
firebase.tenant رقم تعريف المستأجر المرتبط بالحساب، إذا كان متوفّرًا، مثلاً tenant2-m6tyz

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

عندما لا يكون المستخدم الذي يطلب الوصول مسجّلاً الدخول، تكون قيمة المتغيّر auth هي null. يمكنك الاستفادة من ذلك في قواعدك إذا أردت مثلاً حصر إذن الوصول للقراءة على المستخدمين الذين تم التحقّق من هويتهم، أي auth != null. ومع ذلك، ننصح عمومًا بحصر إذن الوصول للكتابة بشكلٍ أكبر.

لمزيد من المعلومات عن المتغيّر auth، يُرجى الاطّلاع على المستندات المرجعية لكلّ من Cloud Firestore و Realtime Database و Cloud Storage.

الاستفادة من معلومات المستخدم في القواعد

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

في قواعدك، حدِّد كيف تتطابق المعلومات في المتغيّر auth (معلومات المستخدم الذي يطلب الوصول) مع معلومات المستخدم المرتبطة بالبيانات المطلوبة.

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

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Realtime Database

{
  "rules": {
    "users": {
      "$userId": {
        // grants write access to the owner of this user account
        // whose uid must exactly match the key ($userId)
        ".write": "$userId === auth.uid"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Only a user can upload their file, but anyone can view it
  match /users/{userId}/{fileName} {
    allow read;
    allow write: if request.auth != null && request.auth.uid == userId;
  }
}

تحديد معلومات مخصّصة عن المستخدم

يمكنك الاستفادة من المتغيّر auth بشكلٍ أكبر لتحديد حقول مخصّصة يتم تعيينها لمستخدمي تطبيقك.

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

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

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents/some_collection: {
    // Remember that, in Cloud Firestore, reads embedded in your rules are billed operations
    write: if request.auth != null && get(/databases/(database)/documents/users/$(request.auth.uid)).data.admin == true;
    read: if request.auth != null;
  }
}

يمكنك الوصول إلى المطالبات المخصّصة في Security Rules بعد إنشاء مطالبات مخصّصة في Authentication. يمكنك بعد ذلك الإشارة إلى هذه المطالبات المخصّصة باستخدام المتغيّر auth.token.

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": {
      "$sub_path": {
      // Create a custom claim for the admin role
      ".write": "auth.uid !== null && auth.token.writer === true",
      ".read": "auth.uid !== null"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Create a custom claim for the admin role
  match /files/{fileName} {
    allow read: if request.auth.uid != null;
    allow write: if request.auth.token.admin == true;
  }
}

للاطّلاع على مزيد من الأمثلة على Security Rules التي تستفيد من Authentication، يُرجى الاطّلاع على قواعد الأمان الأساسية.