يمكنك استخدام 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/{fileName} {
// Disallow
allow create: if !("ranking" in request.resource.metadata)
}
}
}
استخدام البيانات الحالية في Firebase Security Rules
Cloud Firestore
تخزّن العديد من التطبيقات معلومات التحكّم في الوصول كحقول في المستندات في قاعدة البيانات. Cloud Firestore Security Rules يمكن أن تسمح بالوصول أو تمنعه بشكل ديناميكي استنادًا إلى بيانات المستند:
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 لفرض هياكل البيانات والتحقّق من صحة
تنسيق البيانات ومحتواها. Security 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);
Java
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.jsonCloud Storage
عند تقييم القواعد، قد تحتاج أيضًا إلى تقييم البيانات الوصفية للملف الذي يتم تحميله أو تنزيله أو تعديله أو حذفه. يتيح لك ذلك إنشاء قواعد معقّدة وفعّالة تجري عمليات مثل السماح فقط بتحميل الملفات التي تحتوي على أنواع محتوى معيّنة، أو حذف الملفات التي يزيد حجمها عن حجم معيّن فقط.
يحتوي الكائن resource على أزواج من القيم الرئيسية والبيانات الوصفية للملف التي تظهر في كائن
Cloud Storage. يمكن فحص هذه الخصائص في طلبات read أو write لضمان صحّة البيانات. يتحقّق الكائن resource من البيانات الوصفية
للملفات الحالية في مساحة تخزين Cloud Storage.
service firebase.storage {
match /b/{bucket}/o {
match /images {
match /{fileName} {
// 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 {
// 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) Filename (stored in imageId wildcard variable) is less than 32 characters
match /{imageId} {
allow read;
allow write: if request.resource.size < 5 * 1024 * 1024
&& request.resource.contentType.matches('image/.*')
&& request.resource.contentType == resource.contentType
&& imageId.size() < 32
}
}
}
}
تتوفّر قائمة كاملة بالخصائص في الكائن resource في الـ
مستندات المرجعية.