คำแนะนำนี้ต่อยอดจากคำแนะนำการจัดโครงสร้างกฎความปลอดภัย เพื่อแสดงวิธีเพิ่มเงื่อนไขลงใน Cloud Firestore Security Rules หากคุณไม่คุ้นเคยกับพื้นฐานของ Cloud Firestore Security Rules โปรดดูคู่มือเริ่มต้นใช้งาน
องค์ประกอบพื้นฐานหลักของ Cloud Firestore Security Rules คือเงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการหนึ่งๆ ใช้กฎความปลอดภัยเพื่อเขียนเงื่อนไขที่ ตรวจสอบการตรวจสอบสิทธิ์ของผู้ใช้ ตรวจสอบข้อมูลขาเข้า หรือแม้แต่เข้าถึงส่วนอื่นๆ ของ ฐานข้อมูล
พรอมต์ AI สำหรับความช่วยเหลือจาก AI
หากต้องการความช่วยเหลือจาก AI ให้คัดลอกพรอมต์ด้านล่างลงใน เอเจนต์การเขียนโค้ด AI (เช่น Gemini ใน Android Studio, Antigravity, Claude Code, Codex และ Cursor) คุณปรับแต่งพรอมต์และทำซ้ำกับเอเจนต์ได้ ดูข้อมูลการติดตั้งโดยละเอียดได้ที่ ทักษะเอเจนต์ Firebase
Help me use Firebase in my app.
1. Make sure that **Firebase agent skills** are installed and updated. For Claude Code, Codex, or Cursor agents, help me install the Firebase plugin. For other agents, run `npx skills add firebase/agent-skills`. Always try to use **Firebase agent skills** for Firebase-related tasks.
2. Help me write, validate, and deploy Firebase Security Rules to protect my app's Firestore data.
การตรวจสอบสิทธิ์
รูปแบบกฎความปลอดภัยที่พบบ่อยที่สุดอย่างหนึ่งคือการควบคุมการเข้าถึงตาม สถานะการตรวจสอบสิทธิ์ของผู้ใช้ ตัวอย่างเช่น แอปอาจต้องการอนุญาตให้เฉพาะผู้ใช้ที่ลงชื่อเข้าใช้เขียนข้อมูลได้
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() เพื่อเข้าถึงสถานะของเอกสารหลังจากธุรกรรมหรือชุดการเขียนเสร็จสมบูรณ์ แต่ก่อนที่ธุรกรรมหรือชุดจะคอมมิต เช่นเดียวกับ get() ฟังก์ชัน getAfter() จะใช้เส้นทางเอกสารที่ระบุอย่างครบถ้วน คุณใช้ getAfter() เพื่อกำหนดชุดการเขียน
ที่ต้องเกิดขึ้นพร้อมกันเป็นธุรกรรมหรือเป็นกลุ่มได้
เข้าถึงขีดจำกัดการโทร
การเรียกใช้การเข้าถึงเอกสารต่อการประเมินชุดกฎมีขีดจำกัดดังนี้
- 10 สำหรับคำขอเอกสารเดียวและคำขอการค้นหา
-
20 สำหรับการอ่านแบบหลายเอกสาร ธุรกรรม และการเขียนแบบเป็นกลุ่ม ขีดจำกัดก่อนหน้า 10 รายการจะมีผลกับการดำเนินการแต่ละอย่างด้วย
ตัวอย่างเช่น สมมติว่าคุณสร้างคำขอเขียนแบบกลุ่มที่มีการเขียน 3 รายการ และกฎความปลอดภัยใช้การเรียกเข้าถึงเอกสาร 2 รายการเพื่อ ตรวจสอบการเขียนแต่ละรายการ ในกรณีนี้ การเขียนแต่ละครั้งจะใช้การเรียกเข้าถึง 2 ครั้งจาก 10 ครั้ง และคำขอเขียนแบบเป็นกลุ่มจะใช้การเรียกเข้าถึง 6 ครั้งจาก 20 ครั้ง
หากเกินขีดจำกัดใดขีดจำกัดหนึ่ง ระบบจะแสดงข้อผิดพลาด "ปฏิเสธสิทธิ์" ระบบอาจแคชการเรียกใช้การเข้าถึงเอกสารบางรายการ และการเรียกใช้ที่แคชไว้จะไม่นับรวมในโควต้า
ดูคำอธิบายโดยละเอียดเกี่ยวกับผลกระทบของขีดจํากัดเหล่านี้ต่อธุรกรรมและการเขียนแบบเป็นกลุ่มได้ในคู่มือการรักษาความปลอดภัยของการดำเนินการแบบอะตอม
เข้าถึงการโทรและราคา
การใช้ฟังก์ชันเหล่านี้จะดำเนินการอ่านในฐานข้อมูล ซึ่งหมายความว่าระบบจะเรียกเก็บเงินสำหรับการอ่านเอกสารแม้ว่ากฎจะปฏิเสธ คำขอก็ตาม ดูข้อมูลสำหรับการเรียกเก็บเงินที่เฉพาะเจาะจงมากขึ้นได้ที่การกำหนดราคาตามกฎ
ฟังก์ชันที่กำหนดเอง
เมื่อกฎความปลอดภัยมีความซับซ้อนมากขึ้น คุณอาจต้องการรวมชุดเงื่อนไขไว้ในฟังก์ชันที่นำกลับมาใช้ใหม่ได้ในชุดกฎ กฎความปลอดภัย รองรับฟังก์ชันที่กำหนดเอง ไวยากรณ์ของฟังก์ชันที่กำหนดเองจะคล้ายกับ JavaScript แต่ฟังก์ชันของกฎความปลอดภัยจะเขียนในภาษาเฉพาะโดเมน ซึ่งมีข้อจำกัดที่สำคัญบางอย่างดังนี้
- ฟังก์ชันจะมีคำสั่ง
returnได้เพียงคำสั่งเดียว โดยต้องไม่มี ตรรกะเพิ่มเติม เช่น ไม่สามารถเรียกใช้ลูปหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันสามารถเข้าถึงฟังก์ชันและตัวแปรจากขอบเขตที่กำหนดไว้โดยอัตโนมัติ
เช่น ฟังก์ชันที่กำหนดภายในขอบเขต
service cloud.firestoreจะมีสิทธิ์เข้าถึงตัวแปรresourceและฟังก์ชันในตัว เช่นget()และexists() - ฟังก์ชันอาจเรียกฟังก์ชันอื่นๆ ได้ แต่จะเรียกตัวเองซ้ำไม่ได้ ความลึกของสแต็กการเรียกทั้งหมดจำกัดไว้ที่ 10
- ในกฎเวอร์ชัน
v2ฟังก์ชันจะกำหนดตัวแปรได้โดยใช้คีย์เวิร์ดletฟังก์ชันมี let binding ได้สูงสุด 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(); } } }
การใช้ฟังก์ชันในกฎความปลอดภัยจะช่วยให้ดูแลรักษากฎได้ง่ายขึ้นเมื่อกฎมีความซับซ้อนมากขึ้น
กฎไม่ใช่ตัวกรอง
เมื่อรักษาความปลอดภัยให้ข้อมูลและเริ่มเขียนคําค้นหาแล้ว โปรดทราบว่ากฎความปลอดภัยไม่ใช่ตัวกรอง คุณไม่สามารถเขียนการค้นหาสำหรับเอกสารทั้งหมดในคอลเล็กชันและคาดหวังว่ากฎจะแสดงเฉพาะเอกสารที่ไคลเอ็นต์ปัจจุบันมีสิทธิ์เข้าถึง
ตัวอย่างเช่น ลองดูที่กฎความปลอดภัยต่อไปนี้
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 Storage for Firebase โปรดดูวิธีเขียน Cloud Storage Security Rulesเงื่อนไขที่เข้าถึงCloud Firestoreเอกสาร