Catch up on everthing we announced at this year's Firebase Summit. Learn more

تعرف على البنية الأساسية للغة قواعد قاعدة بيانات الوقت الفعلي

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

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

يصف هذا الموضوع البنية الأساسية والبنية قواعد أمان قاعدة البيانات Realtime المستخدمة لإنشاء مجموعات قواعد كاملة.

هيكلة قواعد الأمان الخاصة بك

تتكون قواعد أمان قاعدة البيانات في الوقت الفعلي من تعبيرات تشبه جافا سكريبت مضمنة في مستند JSON. يجب أن يتبع هيكل القواعد الخاصة بك هيكل البيانات التي قمت بتخزينها في قاعدة البيانات الخاصة بك.

القواعد الأساسية في تحديد مجموعة من العقد إلى أن يكون المضمون، وطرق الوصول (على سبيل المثال، القراءة، الكتابة) المعنية، والشروط التي يتم بموجبها إما السماح بالوصول أو رفض. في الأمثلة التالية، سوف يكون شروطنا بسيطة true و false البيانات، ولكن في الموضوع التالي سنقوم تغطية المزيد من الطرق للتعبير عن دينامية الشروط.

لذلك، على سبيل المثال، إذا نحن نحاول تأمين child_node تحت parent_node ، بناء الجملة العام لمتابعة هو:

{
  "rules": {
    "parent_node": {
      "child_node": {
        ".read": <condition>,
        ".write": <condition>,
        ".validate": <condition>,
      }
    }
  }
}

دعونا نطبق هذا النمط. على سبيل المثال ، لنفترض أنك تتعقب قائمة بالرسائل ولديك بيانات تبدو كالتالي:

{
  "messages": {
    "message0": {
      "content": "Hello",
      "timestamp": 1405704370369
    },
    "message1": {
      "content": "Goodbye",
      "timestamp": 1405704395231
    },
    ...
  }
}

يجب أن يتم تنظيم القواعد الخاصة بك بطريقة مماثلة. فيما يلي مجموعة من القواعد للأمان للقراءة فقط والتي قد تكون منطقية لبنية البيانات هذه. يوضح هذا المثال كيف نحدد عقد قاعدة البيانات التي تنطبق عليها القواعد وشروط تقييم القواعد في تلك العقد.

{
  "rules": {
    // For requests to access the 'messages' node...
    "messages": {
      // ...and the individual wildcarded 'message' nodes beneath
      // (we'll cover wildcarding variables more a bit later)....
      "$message": {

        // For each message, allow a read operation if <condition>. In this
        // case, we specify our condition as "true", so read access is always granted.
        ".read": "true",

        // For read-only behavior, we specify that for write operations, our
        // condition is false.
        ".write": "false"
      }
    }
  }
}

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

هناك ثلاثة أنواع من القواعد لفرض الأمن على أساس النوع من العمليات التي يتم تنفيذها على البيانات: .write ، .read ، و .validate . فيما يلي ملخص سريع لأهدافهم:

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

متغيرات التقاط أحرف البدل

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

{
  "rules": {
    "rooms": {
      // this rule applies to any child of /rooms/, the key for each room id
      // is stored inside $room_id variable for reference
      "$room_id": {
        "topic": {
          // the room's topic can be changed if the room id has "public" in it
          ".write": "$room_id.contains('public')"
        }
      }
    }
  }
}

ديناميكية $ ويمكن أيضا أن تستخدم المتغيرات بالتوازي مع أسماء مسار ثابتة. في هذا المثال، نقوم باستخدام $other متغير لإعلان .validate القاعدة التي يضمن أن widget لا يوجد لديه أطفال آخرين من title و color . أي كتابة تؤدي إلى إنشاء المزيد من الأبناء ستفشل.

{
  "rules": {
    "widget": {
      // a widget can have a title or color attribute
      "title": { ".validate": true },
      "color": { ".validate": true },

      // but no other child paths are allowed
      // in this case, $other means any key excluding "title" and "color"
      "$other": { ".validate": false }
    }
  }
}

قراءة وكتابة القواعد تتالي

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

{
  "rules": {
     "foo": {
        // allows read to /foo/*
        ".read": "data.child('baz').val() === true",
        "bar": {
          /* ignored, since read was allowed already */
          ".read": false
        }
     }
  }
}

هذا الهيكل الأمني يسمح /bar/ يجب أن تقرأ من أي وقت /foo/ يحتوي على الطفل baz مع القيمة true . و ".read": false الحكم تحت /foo/bar/ ليس له أي تأثير هنا، منذ وصول لا يمكن أن تلغى بواسطة مسار الطفل.

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

علما بأن .validate القواعد لا تتالي. يجب استيفاء جميع قواعد التحقق على جميع مستويات التسلسل الهرمي للسماح بالكتابة.

القواعد ليست مرشحات

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

{
  "rules": {
    "records": {
      "rec1": {
        ".read": true
      },
      "rec2": {
        ".read": false
      }
    }
  }
}

دون فهم أن القواعد يتم تقييم بالذرة، قد يبدو مثل جلب /records/ مسار سيعود rec1 ولكن ليس rec2 . النتيجة الفعلية ، مع ذلك ، هي خطأ:

جافا سكريبت
var db = firebase.database();
db.ref("records").once("value", function(snap) {
  // success method is not called
}, function(err) {
  // error callback triggered with PERMISSION_DENIED
});
ج موضوعية
ملاحظة: هذا المنتج Firebase لا يتوفر على كليب هدف التطبيقات.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
  // success block is not called
} withCancelBlock:^(NSError * _Nonnull error) {
  // cancel block triggered with PERMISSION_DENIED
}];
سويفت
ملاحظة: هذا المنتج Firebase لا يتوفر على كليب هدف التطبيقات.
var ref = FIRDatabase.database().reference()
ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // success block is not called
}, withCancelBlock: { error in
    // cancel block triggered with PERMISSION_DENIED
})
جافا
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // success method is not called
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback triggered with PERMISSION_DENIED
  });
});
استراحة
curl https://docs-examples.firebaseio.com/rest/records/
# response returns a PERMISSION_DENIED error

منذ عملية قراءة في /records/ غير الذري، وليس هناك حكم قراءة أن منح حق الوصول إلى كافة البيانات تحت /records/ ، وهذا سوف رمي PERMISSION_DENIED الخطأ. إذا كان لنا أن تقييم هذه القاعدة في محاكاة الأمن في منطقتنا وحدة Firebase ، يمكننا أن نرى أن عملية القراءة رفض لأنه لا يوجد حكم قراءة سمحت الوصول إلى /records/ المسار. ومع ذلك، علما بأن قاعدة ل rec1 تم تقييم أبدا لأنه لم يكن في مسار طلبنا. لجلب rec1 ، فإننا بحاجة إلى الوصول إليه مباشرة:

جافا سكريبت
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
ج موضوعية
ملاحظة: هذا المنتج Firebase لا يتوفر على كليب هدف التطبيقات.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
سويفت
ملاحظة: هذا المنتج Firebase لا يتوفر على كليب هدف التطبيقات.
var ref = FIRDatabase.database().reference()
ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in
    // SUCCESS!
})
جافا
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("records/rec1");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
  @Override
  public void onDataChange(DataSnapshot snapshot) {
    // SUCCESS!
  }

  @Override
  public void onCancelled(FirebaseError firebaseError) {
    // error callback is not called
  }
});
استراحة
curl https://docs-examples.firebaseio.com/rest/records/rec1
# SUCCESS!

بيانات متداخلة

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

{
  "rules": {
    "messages": {
      // A rule expression that applies to all nodes in the 'messages' node
      "$message": {
        ".read": "true",
        ".write": "true"
      },
      // A second rule expression applying specifically to the 'message1` node
      "message1": {
        ".read": "false",
        ".write": "false"
      }
    }
  }
}

في المثال أعلاه، يقرأ إلى message1 عقدة سيتم رفض لأن قواعد الثانية هي دائما false ، على الرغم من أن القاعدة الأولى هي دائما true .

الخطوات التالية

يمكنك تعميق فهمك لقواعد أمان قاعدة بيانات Firebase Realtime:

  • تعلم المفهوم الرئيسي القادم للغة قواعد ودينامية الشروط ، والتي تتيح قواعد الاختيار إذن المستخدم، مقارنة البيانات الحالية والقادمة، التحقق من صحة البيانات الواردة، والتحقق من هيكل الاستفسارات القادمة من العميل، وأكثر من ذلك.

  • مراجعة حالات الاستخدام الأمن نموذجية و التعاريف Firebase قواعد الأمن أن عنوان لهم .