Join us for Firebase Summit on November 10, 2021. Tune in to learn how Firebase can help you accelerate app development, release with confidence, and scale with ease. Register

ทดสอบกฎความปลอดภัยของ Cloud Firestore

ขณะที่คุณกำลังสร้างแอป คุณอาจต้องการล็อกการเข้าถึงฐานข้อมูล Cloud Firestore ของคุณ อย่างไรก็ตาม ก่อนที่คุณจะเปิดตัว คุณจะต้องมีกฎความปลอดภัย Cloud Firestore ที่เหมาะสมยิ่งขึ้น ด้วยการจำลองเมฆ FireStore นอกเหนือไปจากการสร้างต้นแบบและทดสอบแอปของคุณ คุณสมบัติทั่วไปและพฤติกรรมที่ คุณสามารถเขียนการทดสอบหน่วยที่ตรวจสอบพฤติกรรมของเมฆ FireStore กฎการรักษาความปลอดภัยของคุณ

เริ่มต้นอย่างรวดเร็ว

ไม่กี่กรณีทดสอบขั้นพื้นฐานที่มีกฎง่ายๆลองใช้ ตัวอย่าง QuickStart

ทำความเข้าใจกฎความปลอดภัยของ Cloud Firestore

Implement Firebase รับรองความถูกต้อง และ กฎเมฆ FireStore การรักษาความปลอดภัย สำหรับการตรวจสอบ serverless การอนุญาตและการตรวจสอบข้อมูลเมื่อคุณใช้ห้องสมุดลูกค้ามือถือและเว็บ

กฎความปลอดภัยของ Cloud Firestore ประกอบด้วยสองส่วน:

  1. match คำสั่งว่าเอกสารที่ระบุในฐานข้อมูลของคุณ
  2. allow การแสดงออกที่การควบคุมการเข้าถึงเอกสารเหล่านั้น

การตรวจสอบสิทธิ์ Firebase จะตรวจสอบข้อมูลรับรองของผู้ใช้และเป็นพื้นฐานสำหรับระบบการเข้าถึงตามผู้ใช้และตามบทบาท

ทุกคำขอฐานข้อมูลจากไลบรารีไคลเอนต์มือถือ/เว็บของ Cloud Firestore จะถูกประเมินตามกฎความปลอดภัยของคุณก่อนที่จะอ่านหรือเขียนข้อมูลใดๆ หากกฎปฏิเสธการเข้าถึงเส้นทางเอกสารที่ระบุ คำขอทั้งหมดจะล้มเหลว

เรียนรู้เพิ่มเติมเกี่ยวกับกฎเมฆ FireStore การรักษาความปลอดภัยในการ เริ่มต้นใช้งานระบบคลาวด์ FireStore กฎการรักษาความปลอดภัย

ติดตั้งโปรแกรมจำลอง

การติดตั้งโปรแกรมจำลองเมฆ FireStore ใช้ Firebase CLI และเรียกใช้คำสั่งดังต่อไปนี้:

firebase setup:emulators:firestore

เรียกใช้โปรแกรมจำลอง

เริ่มต้นด้วยการเริ่มต้นโปรเจ็กต์ Firebase ในไดเรกทอรีการทำงานของคุณ นี่คือขั้นตอนแรกที่พบเมื่อ ใช้ Firebase CLI

firebase init

เริ่มโปรแกรมจำลองโดยใช้คำสั่งต่อไปนี้ โปรแกรมจำลองจะทำงานจนกว่าคุณจะฆ่ากระบวนการ:

firebase emulators:start --only firestore

ในหลายกรณี คุณต้องการเริ่มโปรแกรมจำลอง เรียกใช้ชุดทดสอบ แล้วปิดโปรแกรมจำลองหลังจากเรียกใช้การทดสอบ คุณสามารถทำเช่นนี้ได้อย่างง่ายดายโดยใช้ emulators:exec คำสั่ง:

firebase emulators:exec --only firestore "./my-test-script.sh"

เมื่อเริ่มต้น โปรแกรมจำลองจะพยายามเรียกใช้บนพอร์ตเริ่มต้น (8080) คุณสามารถเปลี่ยนพอร์ตจำลองโดยการปรับเปลี่ยน "emulators" ส่วนที่คุณ firebase.json ไฟล์:

{
  // ...
  "emulators": {
    "firestore": {
      "port": "YOUR_PORT"
    }
  }
}

ก่อนที่คุณจะเรียกใช้โปรแกรมจำลอง

ก่อนที่คุณจะเริ่มใช้โปรแกรมจำลอง ให้คำนึงถึงสิ่งต่อไปนี้:

  • จำลองแรกจะโหลดกฎที่ระบุไว้ใน firestore.rules เขตของคุณ firebase.json ไฟล์ โดยคาดหวังชื่อไฟล์ในเครื่องที่มีกฎความปลอดภัยของ Cloud Firestore และใช้กฎเหล่านั้นกับทุกโครงการ หากคุณไม่ได้ให้เส้นทางของแฟ้มท้องถิ่นหรือใช้ loadFirestoreRules วิธีการตามที่อธิบายไว้ด้านล่างถือว่าจำลองทุกโครงการที่มีกฎระเบียบที่เปิด
  • ในขณะที่ ส่วนใหญ่ Firebase SDK ของ การทำงานที่มีการเลียนแบบโดยตรงเท่านั้น @firebase/rules-unit-testing สนับสนุนห้องสมุดเยาะเย้ย auth ทดสอบหน่วยในกฎความปลอดภัย, การทำง่ายมาก นอกจากนี้ ไลบรารียังสนับสนุนคุณลักษณะเฉพาะของโปรแกรมจำลองบางอย่าง เช่น การล้างข้อมูลทั้งหมด ตามรายการด้านล่าง
  • อีมูเลเตอร์ยังยอมรับโทเค็น Firebase Auth ที่ใช้งานจริงที่จัดหาให้ผ่าน Client SDK และประเมินกฎตามลำดับ ซึ่งช่วยให้เชื่อมต่อแอปพลิเคชันของคุณโดยตรงกับอีมูเลเตอร์ในการผสานรวมและการทดสอบด้วยตนเอง

เรียกใช้การทดสอบหน่วยในพื้นที่

เรียกใช้การทดสอบหน่วยในพื้นที่ด้วย v9 JavaScript SDK

Firebase เผยแพร่ไลบรารีการทดสอบหน่วยกฎความปลอดภัยด้วย JavaScript SDK เวอร์ชัน 9 และ SDK เวอร์ชัน 8 API ของไลบรารีนั้นแตกต่างกันอย่างมาก เราขอแนะนำไลบรารีการทดสอบ v9 ซึ่งมีความคล่องตัวมากกว่าและต้องการการตั้งค่าน้อยกว่าเพื่อเชื่อมต่อกับอีมูเลเตอร์ ดังนั้นจึงหลีกเลี่ยงการใช้ทรัพยากรการผลิตโดยไม่ได้ตั้งใจได้อย่างปลอดภัย หลังเข้ากันได้เรายังคงที่จะทำให้ ห้องสมุดทดสอบ v8 ใช้ได้

ใช้ @firebase/rules-unit-testing โมดูลในการโต้ตอบกับโปรแกรมจำลองที่วิ่งในประเทศ ถ้าคุณได้รับการหมดเวลาหรือ ECONNREFUSED ข้อผิดพลาดตรวจสอบอีกครั้งว่าจำลองกำลังทำงานจริง

เราขอแนะนำให้ใช้รุ่นล่าสุดของ Node.js เพื่อให้คุณสามารถใช้ async/await สัญกรณ์ ลักษณะการทำงานเกือบทั้งหมดที่คุณอาจต้องการทดสอบเกี่ยวข้องกับฟังก์ชันแบบอะซิงโครนัส และโมดูลการทดสอบได้รับการออกแบบให้ทำงานกับโค้ดแบบ Promise

ไลบรารีการทดสอบหน่วยกฎ v9 จะรับรู้ถึงอีมูเลเตอร์เสมอและจะไม่แตะต้องทรัพยากรการผลิตของคุณ

คุณนำเข้าไลบรารีโดยใช้คำสั่งการนำเข้าโมดูลาร์ v9 ตัวอย่างเช่น:

import {
  assertFails,
  assertSucceeds,
  initializeTestEnvironment,
  RulesTestEnvironment,
} from "@firebase/rules-unit-testing"

// Use `const { … } = require("@firebase/rules-unit-testing")` if imports are not supported
// Or we suggest `const testing = require("@firebase/rules-unit-testing")` if necessary.

เมื่อนำเข้าแล้ว การดำเนินการทดสอบหน่วยจะเกี่ยวข้องกับ:

  • การสร้างและการกำหนดค่า RulesTestEnvironment ด้วยการเรียกไปยัง initializeTestEnvironment
  • การตั้งค่าข้อมูลการทดสอบโดยไม่ต้องเรียกหลักเกณฑ์โดยใช้วิธีการอำนวยความสะดวกที่ช่วยให้คุณชั่วคราวบายพาสพวกเขา RulesTestEnvironment.withSecurityRulesDisabled
  • การตั้งค่าชุดทดสอบและต่อการทดสอบก่อน / หลังตะขอกับสายการทำความสะอาดข้อมูลการทดสอบและสิ่งแวดล้อมเช่น RulesTestEnvironment.cleanup() หรือ RulesTestEnvironment.clearFirestore()
  • การดำเนินการกรณีทดสอบที่รัฐรับรองความถูกต้องเลียนแบบโดยใช้ RulesTestEnvironment.authenticatedContext และ RulesTestEnvironment.unauthenticatedContext

วิธีการทั่วไปและฟังก์ชั่นยูทิลิตี้

ยังเห็น วิธีการทดสอบจำลองเฉพาะใน SDK v9

initializeTestEnvironment() => RulesTestEnvironment

ฟังก์ชันนี้เริ่มต้นสภาพแวดล้อมการทดสอบสำหรับการทดสอบหน่วยกฎ เรียกใช้ฟังก์ชันนี้ก่อนสำหรับการตั้งค่าการทดสอบ การดำเนินการที่ประสบความสำเร็จต้องใช้โปรแกรมจำลองการทำงาน

ฟังก์ชั่นรับวัตถุตัวเลือกการกำหนด TestEnvironmentConfig ซึ่งสามารถประกอบด้วยรหัสโครงการและการตั้งค่าโปรแกรมจำลอง

let testEnv = await initializeTestEnvironment({
  projectId: "demo-project-1234",
  firestore: {
    rules: fs.readFileSync("firestore.rules", "utf8"),
  },
});

RulesTestEnvironment.authenticatedContext({ user_id: string, tokenOptions?: TokenOptions }) => RulesTestContext

วิธีการนี้จะสร้าง RulesTestContext ซึ่งพฤติกรรมเช่นผู้ใช้รับรองความถูกต้องรับรองความถูกต้อง คำขอที่สร้างผ่านบริบทที่ส่งคืนจะมีโทเค็นการตรวจสอบสิทธิ์จำลองที่แนบมาด้วย หรือส่งผ่านอ็อบเจ็กต์ที่กำหนดการอ้างสิทธิ์หรือการแทนที่แบบกำหนดเองสำหรับเพย์โหลดโทเค็นการตรวจสอบสิทธิ์

ใช้วัตถุบริบทการทดสอบกลับมาในการทดสอบของคุณเพื่อเข้าถึงกรณีใด ๆ การกำหนดค่าจำลองรวมทั้งผู้ที่กำหนดค่าด้วย initializeTestEnvironment

// Assuming a Firestore app and the Firestore emulator for this example
import { setDoc } from "firebase/firestore";

const alice = testEnv.authenticatedContext("alice", { … });
// Use the Firestore instance associated with this context
await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

RulesTestEnvironment.unauthenticatedContext() => RulesTestContext

วิธีการนี้จะสร้าง RulesTestContext ซึ่งพฤติกรรมเช่นลูกค้าที่ไม่ได้เข้าสู่ระบบผ่านการตรวจสอบ คำขอที่สร้างผ่านบริบทที่ส่งคืนจะไม่มีการแนบโทเค็น Firebase Auth

ใช้วัตถุบริบทการทดสอบกลับมาในการทดสอบของคุณเพื่อเข้าถึงกรณีใด ๆ การกำหนดค่าจำลองรวมทั้งผู้ที่กำหนดค่าด้วย initializeTestEnvironment

// Assuming a Cloud Storage app and the Storage emulator for this example
import { getStorage, ref, deleteObject } from "firebase/storage";

const alice = testEnv.unauthenticatedContext();

// Use the Cloud Storage instance associated with this context
const desertRef = ref(alice.storage(), 'images/desert.jpg');
await assertSucceeds(deleteObject(desertRef));

RulesTestEnvironment.withSecurityRulesDisabled()

เรียกใช้ฟังก์ชันการตั้งค่าการทดสอบด้วยบริบทที่ทำงานเหมือนกับว่ากฎความปลอดภัยถูกปิดใช้งาน

เมธอดนี้ใช้ฟังก์ชันเรียกกลับ ซึ่งใช้บริบทการข้ามกฎความปลอดภัยและส่งคืนสัญญา บริบทจะถูกทำลายเมื่อคำสัญญาได้รับการแก้ไข/ปฏิเสธ

RulesTestEnvironment.cleanup()

วิธีการนี้จะทำลายทุก RulesTestContexts สร้างขึ้นในสภาพแวดล้อมการทดสอบและทำความสะอาดทรัพยากรพื้นฐานที่ช่วยให้ออกทำความสะอาด

วิธีนี้ไม่ได้เปลี่ยนสถานะของอีมูเลเตอร์แต่อย่างใด หากต้องการรีเซ็ตข้อมูลระหว่างการทดสอบ ให้ใช้วิธีล้างข้อมูลเฉพาะโปรแกรมจำลองโปรแกรมจำลอง

assertSucceeds(pr: Promise<any>)) => Promise<any>

นี่คือฟังก์ชันยูทิลิตี้กรณีทดสอบ

ฟังก์ชันนี้ยืนยันว่า Promise ที่ล้อมรอบการดำเนินการจำลองจะได้รับการแก้ไขโดยไม่มีการละเมิดกฎความปลอดภัย

await assertSucceeds(setDoc(alice.firestore(), '/users/alice'), { ... });

assertFails(pr: Promise<any>)) => Promise<any>

นี่คือฟังก์ชันยูทิลิตี้กรณีทดสอบ

ฟังก์ชันนี้ยืนยันว่า Promise ที่ล้อมรอบการดำเนินการจำลองจะถูกปฏิเสธโดยมีการละเมิดกฎความปลอดภัย

await assertFails(setDoc(alice.firestore(), '/users/bob'), { ... });

วิธีการจำเพาะของโปรแกรมจำลอง

ยังเห็น วิธีการทดสอบทั่วไปและฟังก์ชั่นสาธารณูปโภคใน SDK v9

RulesTestEnvironment.clearFirestore() => Promise<void>

วิธีการนี้จะล้างข้อมูลในฐานข้อมูล FireStore ที่เป็นของ projectId กำหนดค่าสำหรับการจำลอง FireStore

RulesTestContext.firestore(settings?: Firestore.FirestoreSettings) => Firestore;

เมธอดนี้รับอินสแตนซ์ Firestore สำหรับบริบทการทดสอบนี้ อินสแตนซ์ Firebase JS Client SDK ที่ส่งคืนสามารถใช้กับไคลเอ็นต์ SDK API (v9 modular หรือ v9 compat)

เห็นภาพการประเมินกฎ

โปรแกรมจำลอง Cloud Firestore ช่วยให้คุณเห็นภาพคำขอของไคลเอ็นต์ใน Emulator Suite UI รวมถึงการติดตามการประเมินสำหรับกฎความปลอดภัยของ Firebase

เปิด FireStore> จองแท็บเพื่อดูลำดับการประเมินผลรายละเอียดสำหรับแต่ละคำขอ

Firestore Emulator Requests Monitor แสดงการประเมินกฎความปลอดภัย

สร้างรายงานการทดสอบ

หลังจากเรียกใช้ชุดการทดสอบแล้ว คุณจะเข้าถึงรายงานความครอบคลุมการทดสอบที่แสดงว่ากฎความปลอดภัยแต่ละข้อได้รับการประเมินอย่างไร

หากต้องการรับรายงาน ให้สอบถามปลายทางที่เปิดเผยบนโปรแกรมจำลองขณะทำงาน สำหรับเวอร์ชันที่เป็นมิตรกับเบราว์เซอร์ ให้ใช้ URL ต่อไปนี้:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage.html

สิ่งนี้แบ่งกฎของคุณออกเป็นนิพจน์และนิพจน์ย่อยที่คุณสามารถวางเมาส์ไว้เพื่อดูข้อมูลเพิ่มเติม รวมถึงจำนวนการประเมินและค่าที่ส่งคืน สำหรับข้อมูลเวอร์ชัน JSON ดิบ ให้รวม URL ต่อไปนี้ในการสืบค้นของคุณ:

http://localhost:8080/emulator/v1/projects/<project_id>:ruleCoverage

ความแตกต่างระหว่างอีมูเลเตอร์และโปรดักชั่น

  1. คุณไม่จำเป็นต้องสร้างโปรเจ็กต์ Cloud Firestore อย่างชัดเจน โปรแกรมจำลองจะสร้างอินสแตนซ์ที่เข้าถึงได้โดยอัตโนมัติ
  2. โปรแกรมจำลอง Cloud Firestore ไม่ทำงานกับโฟลว์การตรวจสอบสิทธิ์ Firebase ปกติ แต่ในการทดสอบ Firebase SDK เราได้ให้ initializeTestApp() วิธีการใน rules-unit-testing ห้องสมุดซึ่งจะใช้เวลา auth ข้อมูล แฮนเดิล Firebase ที่สร้างขึ้นโดยใช้วิธีนี้จะทำงานเหมือนกับว่าได้ตรวจสอบสิทธิ์เรียบร้อยแล้วว่าเป็นเอนทิตีใดก็ตามที่คุณระบุ หากคุณผ่านใน null ก็จะทำตัวเป็นผู้ใช้ที่ไม่ได้รับอนุญาต ( auth != null กฎจะล้มเหลวตัวอย่าง)

แก้ไขปัญหาที่ทราบ

เมื่อคุณใช้โปรแกรมจำลอง Cloud Firestore คุณอาจพบปัญหาที่ทราบต่อไปนี้ ทำตามคำแนะนำด้านล่างเพื่อแก้ไขปัญหาพฤติกรรมผิดปกติที่คุณประสบ หมายเหตุเหล่านี้เขียนขึ้นโดยคำนึงถึงไลบรารีการทดสอบหน่วยกฎความปลอดภัย แต่แนวทางทั่วไปใช้ได้กับ Firebase SDK

พฤติกรรมการทดสอบไม่สอดคล้องกัน

หากการทดสอบของคุณผ่านและล้มเหลวเป็นบางครั้ง แม้จะไม่มีการเปลี่ยนแปลงใดๆ กับการทดสอบเอง คุณอาจต้องตรวจสอบว่ามีการจัดลำดับอย่างถูกต้อง การโต้ตอบกับอีมูเลเตอร์ส่วนใหญ่จะเป็นแบบอะซิงโครนัส ดังนั้นให้ตรวจสอบอีกครั้งว่าโค้ด async ทั้งหมดมีการจัดลำดับอย่างเหมาะสม คุณสามารถแก้ไขลำดับโดยทั้งสัญญาผูกมัดหรือใช้ await สัญกรณ์อิสระ

โดยเฉพาะอย่างยิ่ง ให้ตรวจสอบการดำเนินการ async ต่อไปนี้:

  • การตั้งค่ากฎการรักษาความปลอดภัยด้วยเช่น initializeTestEnvironment
  • การอ่านและเขียนข้อมูลด้วยตัวอย่างเช่น db.collection("users").doc("alice").get()
  • ยืนยันการดำเนินงานรวมทั้ง assertSucceeds และ assertFails

การทดสอบจะผ่านในครั้งแรกที่คุณโหลดโปรแกรมจำลองเท่านั้น

โปรแกรมจำลองเป็นแบบเก็บสถานะ มันเก็บข้อมูลทั้งหมดที่เขียนลงในหน่วยความจำ ดังนั้นข้อมูลใด ๆ จะสูญหายเมื่อใดก็ตามที่โปรแกรมจำลองปิดตัวลง หากคุณกำลังเรียกใช้การทดสอบหลายรายการกับรหัสโปรเจ็กต์เดียวกัน การทดสอบแต่ละรายการสามารถสร้างข้อมูลที่อาจส่งผลต่อการทดสอบในครั้งต่อๆ ไป คุณสามารถใช้วิธีใดๆ ต่อไปนี้เพื่อเลี่ยงการทำงานนี้:

  • ใช้รหัสโปรเจ็กต์ที่ไม่ซ้ำกันสำหรับการทดสอบแต่ละครั้ง โปรดทราบว่าถ้าคุณเลือกที่จะทำเช่นนี้คุณจะต้องเรียก initializeTestEnvironment เป็นส่วนหนึ่งของการทดสอบแต่ละ; กฎจะถูกโหลดโดยอัตโนมัติสำหรับรหัสโปรเจ็กต์เริ่มต้นเท่านั้น
  • ปรับโครงสร้างการทดสอบของคุณใหม่เพื่อไม่ให้โต้ตอบกับข้อมูลที่เขียนไว้ก่อนหน้านี้ (เช่น ใช้คอลเล็กชันที่แตกต่างกันสำหรับการทดสอบแต่ละครั้ง)
  • ลบข้อมูลทั้งหมดที่เขียนระหว่างการทดสอบ

การตั้งค่าการทดสอบมีความซับซ้อนมาก

เมื่อตั้งค่าการทดสอบ คุณอาจต้องการแก้ไขข้อมูลในลักษณะที่กฎความปลอดภัยของ Cloud Firestore ไม่อนุญาตจริงๆ หากกฎของคุณจะทำให้การตั้งค่าที่ซับซ้อนการทดสอบลองใช้ RulesTestEnvironment.withSecurityRulesDisabled ในขั้นตอนการตั้งค่าของคุณเพื่อให้อ่านและเขียนจะไม่เรียก PERMISSION_DENIED ข้อผิดพลาด

หลังจากนั้นการทดสอบของคุณสามารถดำเนินการเป็นผู้ใช้ที่ไม่ได้รับการตรวจสอบสิทธิ์หรือใช้ RulesTestEnvironment.authenticatedContext และ unauthenticatedContext ตามลำดับ วิธีนี้ช่วยให้คุณตรวจสอบว่ากฎความปลอดภัยของ Cloud Firestore อนุญาต/ปฏิเสธกรณีต่างๆ ได้อย่างถูกต้อง