يمكنك استخدام Firebase Security Rules لكتابة بيانات جديدة بشكل مشروط استنادًا إلى البيانات الحالية في قاعدة بياناتك أو حزمة التخزين. يمكنك أيضًا كتابة قواعد تفرض عمليات التحقّق من صحة البيانات من خلال تقييد عمليات الكتابة استنادًا إلى البيانات الجديدة التي يتم كتابتها. اطّلِع على المزيد من المعلومات لمعرفة المزيد عن القواعد التي تستخدِم البيانات الحالية لإنشاء شروط أمان.
اختَر منتجًا في كل قسم للاطّلاع على مزيد من المعلومات عن قواعد التحقّق من صحة البيانات.
القيود المفروضة على البيانات الجديدة
Cloud Firestore
إذا كنت تريد التأكّد من عدم
إنشاء مستند يحتوي على حقل معيّن، يمكنك تضمين الحقل في الشرط allow
. على سبيل المثال، إذا
أردت رفض إنشاء أي مستندات تحتوي على الحقل ranking
،
يمكنك عدم السماح بها في الشرط create
.
service cloud.firestore {
match /databases/{database}/documents {
// Disallow
match /cities/{city} {
allow create: if !("ranking" in request.resource.data)
}
}
}
Realtime Database
إذا كنت تريد التأكّد من عدم إضافة بيانات تحتوي على قيم معيّنة
إلى قاعدة بياناتك، عليك تضمين تلك القيمة في قواعدك وعدم السماح بها
للعمليات الكتابية. على سبيل المثال، إذا كنت تريد رفض أي عمليات كتابة تحتوي على قيم ranking
، عليك منع عمليات الكتابة لأي مستندات تحتوي على قيم ranking
.
{
"rules": {
// Write is allowed for all paths
".write": true,
// Allows writes only if new data doesn't include a `ranking` child value
".validate": "!newData.hasChild('ranking')
}
}
Cloud Storage
إذا كنت تريد التأكّد من عدم
إنشاء ملف يحتوي على بيانات وصفية معيّنة، يمكنك تضمين البيانات الوصفية في الشرط allow
. على سبيل المثال، إذا
كنت تريد رفض إنشاء أي ملفات تحتوي على بيانات وصفية ranking
،
يمكنك منع ذلك في الشرط create
.
service firebase.storage {
match /b/{bucket}/o {
match /files/{allFiles=**} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
استخدام البيانات الحالية في Firebase Security Rules
Cloud Firestore
تخزّن العديد من التطبيقات معلومات التحكّم في الوصول كحقول في المستندات في قاعدة البيانات. يمكن أن تسمح Cloud Firestore Security Rules بشكل ديناميكي بالوصول أو ترفض الوصول استنادًا إلى data المستند:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to read data if the document has the 'visibility'
// field set to 'public'
match /cities/{city} {
allow read: if resource.data.visibility == 'public';
}
}
}
يشير المتغيّر resource
إلى المستند المطلوب، وresource.data
هو
تعيين لجميع الحقول والقيم المخزّنة في المستند. لمزيد من
المعلومات عن المتغيّر resource
، اطّلِع على مستندات
المراجع.
عند كتابة البيانات، قد تحتاج إلى مقارنة البيانات الواردة بالبيانات الحالية. يتيح لك ذلك
تنفيذ إجراءات مثل التأكّد من أنّ الحقل لم يتغيّر، أو أنّه زاد بقيمة واحدة فقط، أو أنّ القيمة الجديدة ستظهر بعد أسبوع على الأقل.
في هذه الحالة، إذا كانت مجموعة القواعد تسمح بالكتابة في انتظار المراجعة، يحتوي المتغيّر request.resource
على الحالة المستقبلية للمستند. بالنسبة إلى عمليات update
التي تُعدِّل فقط مجموعة فرعية من حقول المستند، سيحتوي المتغيّر request.resource
على حالة المستند في انتظار المراجعة بعد العملية. يمكنك التحقّق من قيم الحقل
في request.resource
لمنع تعديلات البيانات غير المرغوب فيها أو غير المتّسقة:
service cloud.firestore {
match /databases/{database}/documents {
// Make sure all cities have a positive population and
// the name is not changed
match /cities/{city} {
allow update: if request.resource.data.population > 0
&& request.resource.data.name == resource.data.name;
}
}
}
Realtime Database
في Realtime Database، استخدِم قواعد .validate
لفرض هياكل البيانات والتحقّق من
تنسيق البيانات ومحتواها. Rules تنفيذ قواعد .validate
بعد
التحقّق من أنّ قاعدة .write
تمنح الإذن بالوصول
لا يتم تطبيق قواعد .validate
بشكل متسلسل. إذا تعذّر تطبيق أي قاعدة تحقّق على أي
مسار أو مسار فرعي في القاعدة، سيتم رفض عملية الكتابة بأكملها.
بالإضافة إلى ذلك، لا تتحقّق تعريفات التحقّق إلا من القيم غير الفارغة، وبذلك يتم تجاهل أي طلبات لحذف البيانات.
راجِع قواعد .validate
التالية:
{
"rules": {
// write is allowed for all paths
".write": true,
"widget": {
// a valid widget must have attributes "color" and "size"
// allows deleting widgets (since .validate is not applied to delete rules)
".validate": "newData.hasChildren(['color', 'size'])",
"size": {
// the value of "size" must be a number between 0 and 99
".validate": "newData.isNumber() &&
newData.val() >= 0 &&
newData.val() <= 99"
},
"color": {
// the value of "color" must exist as a key in our mythical
// /valid_colors/ index
".validate": "root.child('valid_colors/' + newData.val()).exists()"
}
}
}
}
سيؤدي كتابة طلبات في قاعدة بيانات باستخدام القواعد أعلاه إلى النتيجة التالية:
JavaScript
var ref = db.ref("/widget"); // PERMISSION_DENIED: does not have children color and size ref.set('foo'); // PERMISSION DENIED: does not have child color ref.set({size: 22}); // PERMISSION_DENIED: size is not a number ref.set({ size: 'foo', color: 'red' }); // SUCCESS (assuming 'blue' appears in our colors list) ref.set({ size: 21, color: 'blue'}); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child('size').set(99);
Objective-C
FIRDatabaseReference *ref = [[[FIRDatabase database] reference] child: @"widget"]; // PERMISSION_DENIED: does not have children color and size [ref setValue: @"foo"]; // PERMISSION DENIED: does not have child color [ref setValue: @{ @"size": @"foo" }]; // PERMISSION_DENIED: size is not a number [ref setValue: @{ @"size": @"foo", @"color": @"red" }]; // SUCCESS (assuming 'blue' appears in our colors list) [ref setValue: @{ @"size": @21, @"color": @"blue" }]; // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate [[ref child:@"size"] setValue: @99];
Swift
var ref = FIRDatabase.database().reference().child("widget") // PERMISSION_DENIED: does not have children color and size ref.setValue("foo") // PERMISSION DENIED: does not have child color ref.setValue(["size": "foo"]) // PERMISSION_DENIED: size is not a number ref.setValue(["size": "foo", "color": "red"]) // SUCCESS (assuming 'blue' appears in our colors list) ref.setValue(["size": 21, "color": "blue"]) // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
جافا
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("widget"); // PERMISSION_DENIED: does not have children color and size ref.setValue("foo"); // PERMISSION DENIED: does not have child color ref.child("size").setValue(22); // PERMISSION_DENIED: size is not a number Map<String,Object> map = new HashMap<String, Object>(); map.put("size","foo"); map.put("color","red"); ref.setValue(map); // SUCCESS (assuming 'blue' appears in our colors list) map = new HashMap<String, Object>(); map.put("size", 21); map.put("color","blue"); ref.setValue(map); // If the record already exists and has a color, this will // succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) // will fail to validate ref.child("size").setValue(99);
REST
# PERMISSION_DENIED: does not have children color and size curl -X PUT -d 'foo' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION DENIED: does not have child color curl -X PUT -d '{"size": 22}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # PERMISSION_DENIED: size is not a number curl -X PUT -d '{"size": "foo", "color": "red"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # SUCCESS (assuming 'blue' appears in our colors list) curl -X PUT -d '{"size": 21, "color": "blue"}' \ https://docs-examples.firebaseio.com/rest/securing-data/example.json # If the record already exists and has a color, this will # succeed, otherwise it will fail since newData.hasChildren(['color', 'size']) # will fail to validate curl -X PUT -d '99' \ https://docs-examples.firebaseio.com/rest/securing-data/example/size.json
Cloud Storage
عند تقييم القواعد، قد تحتاج أيضًا إلى تقييم البيانات الوصفية للملف الذي يتم تحميله أو تنزيله أو تعديله أو حذفه. يتيح لك ذلك إنشاء قواعد معقدة وفعّالة تؤدي إلى تنفيذ إجراءات، مثل السماح فقط بتحميل ملفات ذات أنواع محتوى معيّنة أو حذف الملفات التي تزيد مساحتها عن حجم معيّن فقط.
يحتوي عنصر resource
على أزواج مفاتيح/قيم مع بيانات وصفية للملف معروضة في عنصر
Cloud Storage. يمكن فحص هذه المواقع عند تلقّي طلبات read
أو
write
لضمان سلامة البيانات. يتحقّق عنصر resource
من البيانات الوصفية
في الملفات الحالية في حزمة Cloud Storage.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{allImages=**} {
// Allow reads if a custom 'visibility' field is set to 'public'
allow read: if resource.metadata.visibility == 'public';
}
}
}
}
يمكنك أيضًا استخدام عنصر request.resource
في طلبات write
(مثل
عمليات التحميل وتعديل البيانات الوصفية والحذف). يحصل عنصر request.resource
على
البيانات الوصفية من الملف الذي سيتم كتابته إذا كان write
مسموحًا به.
يمكنك استخدام هاتين القيمتَين لمنع التعديلات غير المرغوب فيها أو غير المتّسقة أو لفرض قيود التطبيق، مثل نوع الملف أو حجمه.
service firebase.storage {
match /b/{bucket}/o {
match /images {
// Cascade read to any image type at any path
match /{allImages=**} {
allow read;
}
// Allow write files to the path "images/*", subject to the constraints:
// 1) File is less than 5MB
// 2) Content type is an image
// 3) Uploaded content type matches existing content type
// 4) File name (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
تتوفّر قائمة كاملة بالسمات في عنصر resource
في
المستندات المرجعية.