คู่มือนี้ต่อยอดจากคู่มือการจัดโครงสร้างกฎความปลอดภัย เพื่อแสดงวิธีเพิ่มเงื่อนไขลงในCloud Firestore Security Rules หากคุณยังไม่ คุ้นเคยกับข้อมูลเบื้องต้นเกี่ยวกับ Cloud Firestore Security Rules โปรดดู คู่มือเริ่มต้นใช้งาน
องค์ประกอบหลักของ Cloud Firestore Security Rules คือเงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการหนึ่งๆ ใช้กฎความปลอดภัยเพื่อเขียนเงื่อนไขที่ตรวจสอบการตรวจสอบสิทธิ์ผู้ใช้ ตรวจสอบข้อมูลขาเข้า หรือแม้แต่เข้าถึงส่วนอื่นๆ ของฐานข้อมูล
การตรวจสอบสิทธิ์
รูปแบบกฎความปลอดภัยที่พบบ่อยที่สุดอย่างหนึ่งคือการควบคุมการเข้าถึงตามสถานะการตรวจสอบสิทธิ์ของผู้ใช้ ตัวอย่างเช่น แอปของคุณอาจต้องการอนุญาตให้เฉพาะผู้ใช้ที่ลงชื่อเข้าใช้เขียนข้อมูลได้
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 หรือ Google Cloud Identity Platform ตัวแปร request.auth จะมี
ข้อมูลการตรวจสอบสิทธิ์สำหรับไคลเอ็นต์ที่ขอข้อมูล
ดูข้อมูลเพิ่มเติมเกี่ยวกับ request.auth ได้ใน เอกสารอ้างอิง
การตรวจสอบข้อมูล
แอปจำนวนมากจัดเก็บข้อมูลการควบคุมการเข้าถึงเป็นฟิลด์ในเอกสารในฐานข้อมูล 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; } } }
เข้าถึงเอกสารอื่นๆ
กฎความปลอดภัยสามารถประเมินคำขอขาเข้ากับเอกสารอื่นๆ ในฐานข้อมูลได้โดยใช้ฟังก์ชัน get() และ exists() ฟังก์ชัน get() และ exists() ทั้ง 2 ฟังก์ชันคาดหวังเส้นทางเอกสารที่ระบุไว้อย่างครบถ้วน เมื่อใช้ตัวแปรเพื่อสร้างเส้นทางสำหรับ get() และ exists() คุณต้องหลีกเลี่ยงตัวแปรอย่างชัดเจนโดยใช้ไวยากรณ์ $(variable)
ในตัวอย่างด้านล่าง ตัวแปร database จะถูกจับโดยคำสั่ง match
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() เพื่อเข้าถึงสถานะของเอกสารหลังจากธุรกรรมหรือการเขียนแบบเป็นชุดเสร็จสมบูรณ์แล้ว แต่ก่อนที่ธุรกรรมหรือชุดจะคอมมิต ฟังก์ชัน getAfter() จะใช้เส้นทางเอกสารที่ระบุไว้อย่างครบถ้วนเช่นเดียวกับ get() คุณสามารถใช้ getAfter() เพื่อกำหนดชุดการเขียนที่ต้องเกิดขึ้นพร้อมกันเป็นธุรกรรมหรือชุด
ขีดจำกัดการเรียกใช้การเข้าถึง
มีการจำกัดการเรียกใช้การเข้าถึงเอกสารต่อการประเมินชุดกฎ ดังนี้
- 10 รายการสำหรับคำขอเอกสารเดียวและคำขอการค้นหา
-
20 รายการสำหรับการอ่านเอกสารหลายรายการ ธุรกรรม และการเขียนแบบเป็นชุด ขีดจำกัดก่อนหน้า 10 รายการยังใช้กับการดำเนินการแต่ละรายการด้วย
ตัวอย่างเช่น สมมติว่าคุณสร้างคำขอการเขียนแบบเป็นชุดที่มีการดำเนินการเขียน 3 รายการ และกฎความปลอดภัยใช้การเรียกใช้การเข้าถึงเอกสาร 2 รายการเพื่อ ตรวจสอบการเขียนแต่ละรายการ ในกรณีนี้ การเขียนแต่ละรายการจะใช้การเรียกใช้การเข้าถึง 2 รายการจาก 10 รายการ และคำขอการเขียนแบบเป็นชุดจะใช้การเรียกใช้การเข้าถึง 6 รายการจาก 20 รายการ
การเกินขีดจำกัดใดขีดจำกัดหนึ่งจะทำให้เกิดข้อผิดพลาด "สิทธิ์ถูกปฏิเสธ" การเรียกใช้การเข้าถึงเอกสารบางรายการอาจถูกแคช และการเรียกใช้ที่แคชไว้จะไม่นับรวมในขีดจำกัด
ดูคำอธิบายโดยละเอียดเกี่ยวกับวิธีที่ขีดจำกัดเหล่านี้ส่งผลต่อธุรกรรมและการ เขียนแบบเป็นชุดได้ในคู่มือการรักษาความปลอดภัยการดำเนินการแบบอะตอม
การเรียกใช้การเข้าถึงและการกำหนดราคา
การใช้ฟังก์ชันเหล่านี้จะดำเนินการอ่านในฐานข้อมูล ซึ่งหมายความว่าระบบจะเรียกเก็บเงินสำหรับการอ่านเอกสารแม้ว่ากฎจะปฏิเสธคำขอ ดูข้อมูลสำหรับการเรียกเก็บเงินที่เฉพาะเจาะจงมากขึ้นได้ที่Cloud Firestoreการกำหนดราคา
ฟังก์ชันที่กำหนดเอง
เมื่อกฎความปลอดภัยซับซ้อนมากขึ้น คุณอาจต้องการรวมชุดเงื่อนไขไว้ในฟังก์ชันที่คุณสามารถนำไปใช้ซ้ำในชุดกฎได้ กฎความปลอดภัยรองรับฟังก์ชันที่กำหนดเอง ไวยากรณ์ของฟังก์ชันที่กำหนดเองจะคล้ายกับ JavaScript แต่ฟังก์ชันกฎความปลอดภัยเขียนด้วยภาษาเฉพาะโดเมนที่มีข้อจำกัดที่สำคัญบางอย่าง ดังนี้
- ฟังก์ชันจะมีคำสั่ง
returnเพียงรายการเดียวเท่านั้น และไม่มีตรรกะเพิ่มเติม เช่น ฟังก์ชันไม่สามารถดำเนินการลูปหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันสามารถเข้าถึงฟังก์ชันและตัวแปรจากขอบเขตที่กำหนดไว้โดยอัตโนมัติ ตัวอย่างเช่น ฟังก์ชันที่กำหนดไว้ในขอบเขต
service cloud.firestoreจะเข้าถึงตัวแปรresourceและฟังก์ชันในตัว เช่นget()และexists()ได้ - ฟังก์ชันสามารถเรียกใช้ฟังก์ชันอื่นๆ ได้ แต่ไม่สามารถเรียกใช้ฟังก์ชันเดิมซ้ำได้ ความลึกของสแต็กการเรียกใช้ทั้งหมดจำกัดไว้ที่ 10
- ในกฎเวอร์ชัน
v2ฟังก์ชันสามารถกำหนดตัวแปรได้โดยใช้คีย์เวิร์ดletฟังก์ชันสามารถมีการผูกตัวแปรได้สูงสุด 10 รายการ แต่ต้องลงท้ายด้วยคำสั่ง return
ฟังก์ชันจะกำหนดด้วยคีย์เวิร์ด function และรับอาร์กิวเมนต์ได้ตั้งแต่ 0 รายการขึ้นไป ตัวอย่างเช่น คุณอาจต้องการรวมเงื่อนไข 2 ประเภทที่ใช้ในตัวอย่างข้างต้นไว้ในฟังก์ชันเดียว ดังนี้
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());
});
});อนุญาต: กฎนี้อนุญาตการค้นหาต่อไปนี้เนื่องจากอนุประโยค 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 for Firebase โปรดดูวิธี เขียน Cloud Storage Security Rules เงื่อนไขที่เข้าถึงเอกสาร Cloud Firestore