คู่มือนี้สร้างขึ้นจากคู่มือ กฎความปลอดภัยด้านโครงสร้าง เพื่อแสดงวิธีเพิ่มเงื่อนไขให้กับกฎความปลอดภัยของ Cloud Firestore หากคุณไม่คุ้นเคยกับพื้นฐานของกฎความปลอดภัยของ Cloud Firestore โปรดดูคู่มือ เริ่มต้นใช้ งาน
องค์ประกอบหลักของกฎความปลอดภัยของ Cloud Firestore คือเงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการเฉพาะ ใช้กฎความปลอดภัยในการเขียนเงื่อนไขที่ตรวจสอบการรับรองความถูกต้องของผู้ใช้ ตรวจสอบข้อมูลขาเข้า หรือแม้แต่เข้าถึงส่วนอื่นๆ ของฐานข้อมูลของคุณ
การรับรองความถูกต้อง
รูปแบบกฎความปลอดภัยที่พบมากที่สุดรูปแบบหนึ่งคือการควบคุมการเข้าถึงตามสถานะการรับรองความถูกต้องของผู้ใช้ ตัวอย่างเช่น แอปของคุณอาจต้องการอนุญาตให้เฉพาะผู้ใช้ที่ลงชื่อเข้าใช้เขียนข้อมูล:
service cloud.firestore {
match /databases/{database}/documents {
// Allow the user to access documents in the "cities" collection
// only if they are authenticated.
match /cities/{city} {
allow read, write: if request.auth != null;
}
}
}
รูปแบบทั่วไปอีกรูปแบบหนึ่งคือการทำให้แน่ใจว่าผู้ใช้สามารถอ่านและเขียนข้อมูลของตนเองได้เท่านั้น:
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, update, delete: if request.auth != null && request.auth.uid == userId;
allow create: if request.auth != null;
}
}
}
หากแอปของคุณใช้ Firebase Authentication หรือ Google Cloud Identity Platform ตัวแปร request.auth
จะมีข้อมูลการตรวจสอบสิทธิ์สำหรับไคลเอ็นต์ที่ขอข้อมูล สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ request.auth
โปรดดู เอกสารอ้างอิง
การตรวจสอบข้อมูล
แอพจำนวนมากเก็บข้อมูลการควบคุมการเข้าถึงเป็นฟิลด์ในเอกสารในฐานข้อมูล กฎความปลอดภัยของ Cloud Firestore สามารถอนุญาตหรือปฏิเสธการเข้าถึงแบบไดนามิกตามข้อมูลเอกสาร:
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;
}
}
}
เข้าถึงเอกสารอื่นๆ
การใช้ฟังก์ชัน get()
และ exists()
กฎความปลอดภัยของคุณสามารถประเมินคำขอที่เข้ามาเทียบกับเอกสารอื่นๆ ในฐานข้อมูล ฟังก์ชัน get()
และ exists()
ต้องการเส้นทางเอกสารที่ระบุทั้งหมด เมื่อใช้ตัวแปรเพื่อสร้างเส้นทางสำหรับ get()
และ exists()
คุณต้องหลีกเลี่ยงตัวแปรอย่างชัดเจนโดยใช้ไวยากรณ์ $(variable)
ในตัวอย่างด้านล่าง ตัวแปร database
ถูกจับโดยคำสั่งจับ match /databases/{database}/documents
และใช้เพื่อสร้างเส้นทาง:
service cloud.firestore {
match /databases/{database}/documents {
match /cities/{city} {
// Make sure a 'users' document exists for the requesting user before
// allowing any writes to the 'cities' collection
allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))
// Allow the user to delete cities if their user document has the
// 'admin' field set to 'true'
allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
}
}
}
สำหรับการเขียน คุณสามารถใช้ฟังก์ชัน getAfter()
เพื่อเข้าถึงสถานะของเอกสารหลังจากการทำธุรกรรมหรือชุดของการเขียนเสร็จสมบูรณ์ แต่ก่อนการทำธุรกรรมหรือชุดการกระทำ เช่นเดียวกับ get()
ฟังก์ชัน getAfter()
ใช้เส้นทางเอกสารที่ระบุทั้งหมด คุณสามารถใช้ getAfter()
เพื่อกำหนดชุดของการเขียนที่ต้องดำเนินการร่วมกันเป็นธุรกรรมหรือเป็นชุด
เข้าถึงขีด จำกัด การโทร
มีข้อจำกัดในการเรียกใช้การเข้าถึงเอกสารต่อการประเมินชุดกฎ:
- 10 สำหรับคำขอเอกสารเดี่ยวและคำขอเคียวรี
20 สำหรับการอ่านหลายเอกสาร ธุรกรรม และการเขียนเป็นชุด ขีดจำกัด 10 ก่อนหน้านี้ใช้กับการดำเนินการแต่ละครั้งด้วย
ตัวอย่างเช่น สมมติว่าคุณสร้างคำขอเขียนแบบกลุ่มที่มีการดำเนินการเขียน 3 ครั้ง และกฎความปลอดภัยของคุณใช้การเรียกใช้การเข้าถึงเอกสาร 2 ครั้งเพื่อตรวจสอบความถูกต้องของการเขียนแต่ละครั้ง ในกรณีนี้ การเขียนแต่ละครั้งใช้การเรียกใช้การเข้าถึง 2 จาก 10 ครั้ง และคำขอเขียนแบบแบทช์ใช้การเรียกใช้การเข้าถึง 6 จาก 20 ครั้ง
เกินขีด จำกัด ส่งผลให้เกิดข้อผิดพลาดในการอนุญาตการปฏิเสธ การเรียกใช้การเข้าถึงเอกสารบางรายการอาจถูกแคช และการเรียกที่แคชจะไม่นับรวมในขีดจำกัด
สำหรับคำอธิบายโดยละเอียดเกี่ยวกับผลกระทบของข้อจำกัดเหล่านี้ต่อธุรกรรมและการเขียนเป็นชุด โปรดดูคำแนะนำสำหรับ การรักษาความปลอดภัยของการดำเนินการระดับปรมาณู
เข้าถึงการโทรและการกำหนดราคา
การใช้ฟังก์ชันเหล่านี้ดำเนินการอ่านในฐานข้อมูลของคุณ ซึ่งหมายความว่าคุณจะถูกเรียกเก็บเงินสำหรับการอ่านเอกสารแม้ว่ากฎของคุณจะปฏิเสธคำขอก็ตาม ดู ราคา Cloud Firestore สำหรับข้อมูลการเรียกเก็บเงินที่เฉพาะเจาะจงมากขึ้น
ฟังก์ชั่นที่กำหนดเอง
เมื่อกฎความปลอดภัยของคุณซับซ้อนมากขึ้น คุณอาจต้องการรวมชุดเงื่อนไขในฟังก์ชันที่คุณใช้ซ้ำได้ในชุดกฎของคุณ กฎความปลอดภัยรองรับฟังก์ชันแบบกำหนดเอง ไวยากรณ์สำหรับฟังก์ชันแบบกำหนดเองจะคล้ายกับ JavaScript แต่ฟังก์ชันกฎความปลอดภัยเขียนด้วยภาษาเฉพาะโดเมนซึ่งมีข้อจำกัดที่สำคัญบางประการ:
- ฟังก์ชันสามารถมีคำสั่ง
return
เดียวเท่านั้น ไม่สามารถมีตรรกะเพิ่มเติมใดๆ ตัวอย่างเช่น พวกเขาไม่สามารถดำเนินการวนซ้ำหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันสามารถเข้าถึงฟังก์ชันและตัวแปรโดยอัตโนมัติจากขอบเขตที่กำหนดไว้ ตัวอย่างเช่น ฟังก์ชันที่กำหนดภายในขอบเขต
service cloud.firestore
มีสิทธิ์เข้าถึงตัวแปรresource
และฟังก์ชันในตัว เช่นget()
และexists()
- ฟังก์ชันอาจเรียกใช้ฟังก์ชันอื่นแต่ไม่สามารถเรียกซ้ำได้ ความลึกของ call stack ทั้งหมดจำกัดอยู่ที่ 10
- ในกฎเวอร์ชัน
v2
ฟังก์ชันสามารถกำหนดตัวแปรโดยใช้คำหลักlet
ฟังก์ชันสามารถมีได้มากถึง 10 การรวม let แต่ต้องลงท้ายด้วยคำสั่ง return
ฟังก์ชันถูกกำหนดด้วยคีย์เวิร์ดของ function
และรับอาร์กิวเมนต์เป็นศูนย์หรือมากกว่านั้น ตัวอย่างเช่น คุณอาจต้องการรวมเงื่อนไขสองประเภทที่ใช้ในตัวอย่างด้านบนเป็นฟังก์ชันเดียว:
service cloud.firestore {
match /databases/{database}/documents {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /cities/{city} {
allow read, write: if signedInOrPublic();
}
match /users/{user} {
allow read, write: if signedInOrPublic();
}
}
}
การใช้ฟังก์ชันในกฎความปลอดภัยทำให้รักษาได้มากขึ้นตามความซับซ้อนของกฎที่เพิ่มขึ้น
กฎไม่ใช่ตัวกรอง
เมื่อคุณรักษาความปลอดภัยของข้อมูลและเริ่มเขียนแบบสอบถามแล้ว โปรดทราบว่ากฎความปลอดภัยไม่ใช่ตัวกรอง คุณไม่สามารถเขียนแบบสอบถามสำหรับเอกสารทั้งหมดในคอลเลกชั่น และคาดว่า Cloud Firestore จะส่งคืนเฉพาะเอกสารที่ไคลเอนต์ปัจจุบันมีสิทธิ์เข้าถึง
ตัวอย่างเช่น ใช้กฎความปลอดภัยต่อไปนี้:
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';
}
}
}
ปฏิเสธ : กฎนี้ปฏิเสธข้อความค้นหาต่อไปนี้ เนื่องจากชุดผลลัพธ์สามารถรวมเอกสารที่ visibility
ไม่เปิดเผยต่อ public
:
เว็บ
db.collection("cities").get() .then(function(querySnapshot) { querySnapshot.forEach(function(doc) { console.log(doc.id, " => ", doc.data()); }); });
Allowed : กฎนี้อนุญาตการสืบค้นต่อไปนี้เนื่องจากคำสั่ง where("visibility", "==", "public")
รับประกันว่าชุดผลลัพธ์ตรงตามเงื่อนไขของกฎ:
เว็บ
db.collection("cities").where("visibility", "==", "public").get() .then(function(querySnapshot) { querySnapshot.forEach(function(doc) { console.log(doc.id, " => ", doc.data()); }); });
กฎความปลอดภัยของ Cloud Firestore จะประเมินการสืบค้นแต่ละรายการเทียบกับผลลัพธ์ที่เป็นไปได้ และดำเนินการตามคำขอหากสามารถส่งคืนเอกสารที่ไคลเอนต์ไม่มีสิทธิ์อ่าน ข้อความค้นหาต้องเป็นไปตามข้อจำกัดที่กำหนดโดยกฎความปลอดภัยของคุณ สำหรับข้อมูลเพิ่มเติมเกี่ยวกับกฎความปลอดภัยและการสืบค้น โปรดดูที่ การสืบค้นข้อมูลอย่างปลอดภัย
ขั้นตอนถัดไป
- เรียนรู้ว่า กฎความปลอดภัยส่งผลต่อข้อความค้นหาของคุณ อย่างไร
- เรียนรู้วิธี จัดโครงสร้างกฎความปลอดภัย
- อ่าน การอ้างอิงกฎความปลอดภัย
- สำหรับแอปที่ใช้ Cloud Storage สำหรับ Firebase ให้เรียนรู้วิธี เขียนเงื่อนไขกฎความปลอดภัยของ Cloud Storage ที่เข้าถึงเอกสาร Cloud Firestore