คู่มือนี้สร้างขึ้นจากคำแนะนำการกำหนดโครงสร้างกฎความปลอดภัยเพื่อแสดงวิธีเพิ่มเงื่อนไขในกฎความปลอดภัยของ 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 หรือ 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()
คุณต้องกำหนด Escape ตัวแปรอย่างชัดเจนโดยใช้ไวยากรณ์ $(variable)
ในตัวอย่างด้านล่าง คำสั่งจับคู่ match /databases/{database}/documents
จะบันทึกตัวแปร database
และใช้เพื่อสร้างเส้นทาง
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
ได้ ฟังก์ชันมีการเชื่อมโยง Let ๆ ได้สูงสุด 10 รายการ แต่ต้องสิ้นสุดด้วยคำสั่งส่งกลับ
ระบบจะกำหนดฟังก์ชันด้วยคีย์เวิร์ด function
และไม่มีอาร์กิวเมนต์ใดๆ เช่น คุณอาจต้องการรวมเงื่อนไข 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 ที่เข้าถึงเอกสาร Cloud Firestore สำหรับแอปที่ใช้ Cloud Storage for Firebase