คำแนะนำนี้ต่อยอดจากคำแนะนำการจัดโครงสร้างกฎความปลอดภัย เพื่อแสดงวิธีเพิ่มเงื่อนไขลงใน 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 /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()
- ฟังก์ชันอาจเรียกฟังก์ชันอื่นๆ ได้ แต่จะเรียกตัวเองซ้ำไม่ได้ ความลึกของสแต็กการเรียกทั้งหมดถูกจำกัดไว้ที่ 10
- ในกฎเวอร์ชัน
v2
ฟังก์ชันจะกำหนดตัวแปรได้โดยใช้คีย์เวิร์ดlet
ฟังก์ชันมีได้สูงสุด 10 การเชื่อมโยง let แต่ต้องลงท้ายด้วยคำสั่ง 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เอกสาร