คู่มือนี้ต่อยอดมาจากคู่มือการจัดโครงสร้างกฎความปลอดภัยเพื่อแสดงวิธีเพิ่มเงื่อนไขลงใน Cloud Firestore Security Rules หากคุณไม่คุ้นเคยกับพื้นฐานของ Cloud Firestore Security Rules โปรดดูคู่มือเริ่มต้นใช้งาน
องค์ประกอบพื้นฐานหลักของ Cloud Firestore Security Rules คือเงื่อนไข เงื่อนไขคือนิพจน์บูลีนที่กำหนดว่าควรอนุญาตหรือปฏิเสธการดำเนินการหนึ่งๆ ใช้กฎความปลอดภัยเพื่อเขียนเงื่อนไขที่ตรวจสอบการตรวจสอบสิทธิ์ผู้ใช้ ตรวจสอบข้อมูลขาเข้า หรือแม้แต่เข้าถึงส่วนอื่นๆ ของฐานข้อมูล
พรอมต์ AI รายการสำหรับความช่วยเหลือจาก AI
หากต้องการความช่วยเหลือจาก AI ให้คัดลอกพรอมต์ด้านล่างลงในตัวแทนการเขียนโค้ด AI (เช่น Gemini ใน Android Studio, Antigravity, Claude Code, Codex และ Cursor) คุณสามารถปรับแต่งพรอมต์และปรับปรุงซ้ำๆ กับ Agent ได้ ดูข้อมูลการติดตั้งโดยละเอียดได้ที่ทักษะเอเจนต์ 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() ต้องใช้เส้นทางเอกสารที่ระบุไว้อย่างสมบูรณ์ เมื่อใช้ตัวแปรเพื่อสร้างเส้นทางสำหรับ 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() เพื่อเข้าถึงสถานะของเอกสารหลังจากธุรกรรมหรือกลุ่มการเขียนเสร็จสมบูรณ์ แต่ก่อนที่ธุรกรรมหรือกลุ่มจะคอมมิต ฟังก์ชัน getAfter() จะใช้เส้นทางเอกสารที่ระบุไว้อย่างสมบูรณ์เช่นเดียวกับ get() คุณสามารถใช้ getAfter() เพื่อกำหนดชุดการเขียนที่ต้องเกิดขึ้นพร้อมกันเป็นธุรกรรมหรือกลุ่ม
ขีดจำกัดการโทรเข้าถึง
มีการจำกัดการเรียกใช้การเข้าถึงเอกสารต่อการประเมินชุดกฎ ดังนี้
- 10 สำหรับคำขอเอกสารเดียวและคำขอการค้นหา
-
20 สำหรับการอ่านหลายเอกสาร ธุรกรรม และการเขียนแบบกลุ่ม ขีดจำกัดก่อนหน้านี้ที่ 10 รายการยังมีผลกับการดำเนินการแต่ละรายการด้วย
ตัวอย่างเช่น สมมติว่าคุณสร้างคำขอเขียนแบบเป็นกลุ่มที่มีการดำเนินการเขียน 3 รายการ และกฎความปลอดภัยใช้การเรียกใช้การเข้าถึงเอกสาร 2 ครั้งเพื่อตรวจสอบการเขียนแต่ละครั้ง ในกรณีนี้ การเขียนแต่ละครั้งจะใช้การเรียกการเข้าถึง 2 ครั้งจาก 10 ครั้ง และคำขอเขียนแบบเป็นกลุ่มจะใช้การเรียกการเข้าถึง 6 ครั้งจาก 20 ครั้ง
หากเกินขีดจำกัดอย่างใดอย่างหนึ่ง ระบบจะแสดงข้อผิดพลาด "สิทธิ์ถูกปฏิเสธ" ระบบอาจแคชการเรียกใช้การเข้าถึงเอกสารบางรายการ และการเรียกใช้ที่แคชไว้จะไม่นับรวมในขีดจำกัด
ดูคำอธิบายโดยละเอียดเกี่ยวกับผลกระทบของขีดจำกัดเหล่านี้ต่อธุรกรรมและการเขียนแบบกลุ่มได้ที่คู่มือการรักษาความปลอดภัยของการดำเนินการแบบอะตอม
การเข้าถึงการโทรและราคา
การใช้ฟังก์ชันเหล่านี้จะดำเนินการอ่านในฐานข้อมูล ซึ่งหมายความว่าระบบจะเรียกเก็บเงินสำหรับการอ่านเอกสารแม้ว่ากฎจะปฏิเสธคำขอก็ตาม ดูข้อมูลสำหรับการเรียกเก็บเงินที่เฉพาะเจาะจงมากขึ้นได้ที่ราคาของกฎ
ฟังก์ชันที่กำหนดเอง
เมื่อกฎความปลอดภัยมีความซับซ้อนมากขึ้น คุณอาจต้องการรวมชุดเงื่อนไขไว้ในฟังก์ชันที่สามารถนำมาใช้ซ้ำในชุดกฎได้ กฎความปลอดภัยรองรับฟังก์ชันที่กำหนดเอง ไวยากรณ์สำหรับฟังก์ชันที่กำหนดเองจะคล้ายกับ JavaScript เล็กน้อย แต่ฟังก์ชันกฎความปลอดภัยจะเขียนด้วยภาษาเฉพาะโดเมน ซึ่งมีข้อจำกัดที่สำคัญบางประการดังนี้
- ฟังก์ชันมีคำสั่ง
returnได้เพียงคำสั่งเดียวเท่านั้น และต้องไม่มีตรรกะเพิ่มเติมใดๆ เช่น ไม่สามารถเรียกใช้ลูปหรือเรียกใช้บริการภายนอกได้ - ฟังก์ชันจะเข้าถึงฟังก์ชันและตัวแปรจากขอบเขตที่กำหนดไว้ได้โดยอัตโนมัติ เช่น ฟังก์ชันที่กำหนดไว้ภายในขอบเขต
service cloud.firestoreจะมีสิทธิ์เข้าถึงตัวแปรresourceและฟังก์ชันในตัว เช่นget()และexists() - ฟังก์ชันอาจเรียกใช้ฟังก์ชันอื่นๆ ได้ แต่จะเรียกซ้ำไม่ได้ ความลึกของสแต็กการเรียกใช้ทั้งหมดจำกัดอยู่ที่ 10
- ในกฎเวอร์ชัน
v2ฟังก์ชันสามารถกำหนดตัวแปรโดยใช้คีย์เวิร์ดletฟังก์ชันสามารถมีการเชื่อมโยง 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(); } } }
การใช้ฟังก์ชันในกฎความปลอดภัยจะช่วยให้ดูแลรักษาได้ง่ายขึ้นเมื่อกฎมีความซับซ้อนมากขึ้น
กฎไม่ใช่ตัวกรอง
เมื่อรักษาความปลอดภัยของข้อมูลและเริ่มเขียนการค้นหาแล้ว โปรดทราบว่ากฎความปลอดภัยไม่ใช่ตัวกรอง คุณไม่สามารถเขียนการค้นหาสำหรับเอกสารทั้งหมดในคอลเล็กชันและคาดหวังให้กฎแสดงเฉพาะเอกสารที่ไคลเอ็นต์ปัจจุบันมีสิทธิ์เข้าถึง
ตัวอย่างเช่น ลองดูกฎความปลอดภัยต่อไปนี้
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