Kiểm tra Quy tắc bảo mật Cloud Firestore của bạn

Khi đang xây dựng ứng dụng của mình, bạn có thể muốn khóa quyền truy cập vào cơ sở dữ liệu Cloud Firestore của mình. Tuy nhiên, trước khi khởi chạy, bạn sẽ cần Quy tắc bảo mật Cloud Firestore nhiều sắc thái hơn. Với giả lập Mây FireStore, ngoài việc tạo mẫu và thử nghiệm ứng dụng của bạn tính năng và hành vi chung , bạn có thể viết các bài kiểm tra đơn vị kiểm tra hành vi của Security Rules FireStore Cloud của bạn.

Bắt đầu nhanh

Đối với một vài trường hợp thử nghiệm cơ bản với quy tắc đơn giản, hãy thử các mẫu QuickStart .

Hiểu các quy tắc bảo mật Cloud Firestore

Thực hiện căn cứ hỏa lực xác thựcSecurity Rules FireStore đám mây để xác thực serverless, ủy quyền, và xác nhận dữ liệu khi bạn sử dụng các thư viện client di động và web.

Quy tắc bảo mật Cloud Firestore bao gồm hai phần:

  1. Một match tuyên bố danh sách chỉ rõ tài liệu trong cơ sở dữ liệu của bạn.
  2. Một allow biểu thức điều khiển truy cập vào các văn bản đó.

Xác thực Firebase xác minh thông tin đăng nhập của người dùng và cung cấp nền tảng cho các hệ thống truy cập dựa trên vai trò và người dùng.

Mọi yêu cầu cơ sở dữ liệu từ thư viện khách hàng di động / web Cloud Firestore đều được đánh giá dựa trên các quy tắc bảo mật của bạn trước khi đọc hoặc ghi bất kỳ dữ liệu nào. Nếu các quy tắc từ chối quyền truy cập vào bất kỳ đường dẫn tài liệu nào được chỉ định, thì toàn bộ yêu cầu sẽ không thành công.

Tìm hiểu thêm về Cloud Rules FireStore an Bắt đầu với Cloud Security Rules FireStore .

Cài đặt trình giả lập

Để cài đặt giả lập Mây FireStore, sử dụng các căn cứ hỏa lực CLI và chạy lệnh dưới đây:

firebase setup:emulators:firestore

Chạy trình giả lập

Bắt đầu bằng cách khởi tạo một dự án Firebase trong thư mục làm việc của bạn. Đây là một bước đầu tiên phổ biến khi sử dụng các căn cứ hỏa lực CLI .

firebase init

Khởi động trình giả lập bằng lệnh sau. Trình giả lập sẽ chạy cho đến khi bạn kết thúc quá trình:

firebase emulators:start --only firestore

Trong nhiều trường hợp, bạn muốn khởi động trình giả lập, hãy chạy bộ thử nghiệm, sau đó tắt trình mô phỏng sau khi chạy thử nghiệm. Bạn có thể làm điều này một cách dễ dàng bằng cách sử dụng emulators:exec lệnh:

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

Khi khởi động, trình giả lập sẽ cố gắng chạy trên một cổng mặc định (8080). Bạn có thể thay đổi các cổng giả lập bằng cách sửa đổi "emulators" phần của bạn firebase.json file:

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

Trước khi bạn chạy trình giả lập

Trước khi bạn bắt đầu sử dụng trình giả lập, hãy ghi nhớ những điều sau:

  • Các giả lập ban đầu sẽ được tải các quy tắc quy định trong firestore.rules lĩnh vực của bạn firebase.json tập tin. Nó mong đợi tên của một tệp cục bộ chứa Quy tắc bảo mật Cloud Firestore của bạn và áp dụng các quy tắc đó cho tất cả các dự án. Nếu bạn không cung cấp các đường dẫn tập tin địa phương hoặc sử dụng loadFirestoreRules phương pháp như mô tả dưới đây, xử lý giả lập tất cả các dự án là có quy tắc mở.
  • Trong khi hầu hết các căn cứ hỏa lực SDK làm việc với các giả lập trực tiếp, chỉ có @firebase/rules-unit-testing hỗ trợ thư viện chế giễu auth trong Quy định an toàn, làm các xét nghiệm đơn vị dễ dàng hơn nhiều. Ngoài ra, thư viện hỗ trợ một số tính năng dành riêng cho trình giả lập như xóa tất cả dữ liệu, như được liệt kê bên dưới.
  • Trình giả lập cũng sẽ chấp nhận mã thông báo Firebase Auth sản xuất được cung cấp thông qua SDK ứng dụng khách và đánh giá các quy tắc cho phù hợp, cho phép kết nối ứng dụng của bạn trực tiếp với trình giả lập trong quá trình tích hợp và kiểm tra thủ công.

Chạy thử nghiệm đơn vị cục bộ

Chạy thử nghiệm đơn vị cục bộ với SDK JavaScript v9

Firebase phân phối thư viện thử nghiệm đơn vị Quy tắc bảo mật với cả SDK JavaScript phiên bản 9 và SDK phiên bản 8 của nó. Các API thư viện khác nhau đáng kể. Chúng tôi khuyên bạn nên sử dụng thư viện thử nghiệm v9, được sắp xếp hợp lý hơn và yêu cầu ít thiết lập hơn để kết nối với trình giả lập và do đó tránh sử dụng ngẫu nhiên tài nguyên sản xuất một cách an toàn. Đối với khả năng tương thích ngược, chúng tôi tiếp tục làm cho các thư viện test v8 sẵn .

Sử dụng @firebase/rules-unit-testing module để tương tác với các giả lập mà chạy cục bộ. Nếu bạn nhận được timeout hoặc ECONNREFUSED lỗi, kiểm tra lại rằng giả lập được thực sự chạy.

Chúng tôi khuyên bạn sử dụng một phiên bản gần đây của Node.js, do đó bạn có thể sử dụng async/await ký hiệu. Hầu như tất cả các hành vi bạn có thể muốn kiểm tra đều liên quan đến các chức năng không đồng bộ và mô-đun kiểm tra được thiết kế để hoạt động với mã dựa trên Promise.

Thư viện Kiểm tra Đơn vị Quy tắc v9 luôn biết các trình giả lập và không bao giờ động đến tài nguyên sản xuất của bạn.

Bạn nhập thư viện bằng cách sử dụng câu lệnh nhập mô-đun v9. Ví dụ:

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.

Sau khi được nhập, việc triển khai các bài kiểm tra đơn vị bao gồm:

  • Tạo và cấu hình một RulesTestEnvironment với một cuộc gọi đến initializeTestEnvironment .
  • Thiết lập dữ liệu thử nghiệm mà không cần kích hoạt Quy định, sử dụng một phương pháp thuận tiện cho phép bạn tạm thời bỏ qua họ, RulesTestEnvironment.withSecurityRulesDisabled .
  • Thiết lập bộ kiểm tra và mỗi bài kiểm tra trước / sau móc với các cuộc gọi đến dọn dẹp dữ liệu thử nghiệm và môi trường, như RulesTestEnvironment.cleanup() hoặc RulesTestEnvironment.clearFirestore() .
  • Thực hiện trường hợp kiểm tra rằng các quốc gia xác thực bắt chước sử dụng RulesTestEnvironment.authenticatedContextRulesTestEnvironment.unauthenticatedContext .

Các phương pháp phổ biến và các chức năng tiện ích

Xem thêm các phương pháp thử nghiệm giả lập cụ thể trong SDK v9 .

initializeTestEnvironment() => RulesTestEnvironment

Chức năng này khởi tạo một môi trường thử nghiệm để thử nghiệm đơn vị quy tắc. Gọi chức năng này trước để thiết lập thử nghiệm. Việc thực thi thành công yêu cầu trình giả lập đang chạy.

Chức năng chấp nhận một đối tượng tùy chọn xác định một TestEnvironmentConfig , có thể bao gồm một ID dự án và giả lập các thiết lập cấu hình.

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

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

Phương pháp này tạo ra một RulesTestContext , mà cư xử như một chứng thực xác thực người dùng. Các yêu cầu được tạo thông qua ngữ cảnh được trả về sẽ có mã thông báo Xác thực giả được đính kèm. Theo tùy chọn, chuyển một đối tượng xác định xác nhận quyền sở hữu hoặc ghi đè tùy chỉnh cho tải trọng mã thông báo Xác thực.

Sử dụng các đối tượng bối cảnh thử nghiệm trở lại trong các thử nghiệm của bạn để truy cập bất kỳ trường hợp giả lập cấu hình, bao gồm cả những cấu hình với 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

Phương pháp này tạo ra một RulesTestContext , mà cư xử như một khách hàng mà không được đăng nhập qua xác thực. Các yêu cầu được tạo thông qua ngữ cảnh được trả về sẽ không có mã thông báo Firebase Auth được đính kèm.

Sử dụng các đối tượng bối cảnh thử nghiệm trở lại trong các thử nghiệm của bạn để truy cập bất kỳ trường hợp giả lập cấu hình, bao gồm cả những cấu hình với 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()

Chạy chức năng thiết lập thử nghiệm với ngữ cảnh hoạt động như thể Quy tắc bảo mật đã bị vô hiệu hóa.

Phương thức này sử dụng một hàm gọi lại, hàm này nhận bối cảnh Bảo mật-Quy tắc-bỏ qua và trả về một lời hứa. Bối cảnh sẽ bị phá hủy khi lời hứa được giải quyết / từ chối.

RulesTestEnvironment.cleanup()

Phương pháp này phá hủy tất cả RulesTestContexts tạo ra trong môi trường thử nghiệm và dọn dẹp các nguồn lực cơ bản, cho phép một lối ra sạch.

Phương pháp này không thay đổi trạng thái của trình giả lập theo bất kỳ cách nào. Để đặt lại dữ liệu giữa các lần kiểm tra, hãy sử dụng phương pháp dữ liệu rõ ràng dành riêng cho trình mô phỏng ứng dụng.

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

Đây là một chức năng tiện ích trường hợp thử nghiệm.

Chức năng xác nhận rằng Promise được cung cấp gói một hoạt động giả lập sẽ được giải quyết mà không vi phạm Quy tắc bảo mật.

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

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

Đây là một chức năng tiện ích trường hợp thử nghiệm.

Hàm xác nhận rằng Promise được cung cấp gói một hoạt động giả lập sẽ bị từ chối do vi phạm Quy tắc bảo mật.

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

Các phương pháp dành riêng cho trình giả lập

Xem thêm các phương pháp thử nghiệm chung và chức năng tiện ích trong SDK v9 .

RulesTestEnvironment.clearFirestore() => Promise<void>

Phương pháp này xóa dữ liệu trong cơ sở dữ liệu FireStore rằng thuộc về projectId cấu hình cho giả lập FireStore.

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

Phương thức này nhận được một phiên bản Firestore cho ngữ cảnh thử nghiệm này. Phiên bản SDK ứng dụng khách Firebase JS trả về có thể được sử dụng với các API SDK ứng dụng khách (v9 mô-đun hoặc v9 compat).

Trực quan hóa các đánh giá quy tắc

Trình giả lập Cloud Firestore cho phép bạn trực quan hóa các yêu cầu của khách hàng trong Giao diện người dùng của Emulator Suite, bao gồm theo dõi đánh giá cho Quy tắc bảo mật của Firebase.

Mở FireStore> tab Các yêu cầu để xem trình tự đánh giá chi tiết cho mỗi yêu cầu.

Màn hình yêu cầu trình giả lập Firestore hiển thị đánh giá Quy tắc bảo mật

Tạo báo cáo thử nghiệm

Sau khi chạy một bộ kiểm tra, bạn có thể truy cập các báo cáo phạm vi kiểm tra cho biết từng quy tắc bảo mật của bạn đã được đánh giá như thế nào.

Để nhận báo cáo, hãy truy vấn một điểm cuối được tiếp xúc trên trình giả lập khi nó đang chạy. Đối với phiên bản thân thiện với trình duyệt, hãy sử dụng URL sau:

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

Điều này phá vỡ các quy tắc của bạn thành các biểu thức và biểu thức con mà bạn có thể di chuột qua để biết thêm thông tin, bao gồm số lượng đánh giá và giá trị được trả về. Đối với phiên bản JSON thô của dữ liệu này, hãy bao gồm URL sau trong truy vấn của bạn:

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

Sự khác biệt giữa trình giả lập và sản xuất

  1. Bạn không cần phải tạo dự án Cloud Firestore một cách rõ ràng. Trình giả lập tự động tạo bất kỳ phiên bản nào được truy cập.
  2. Trình mô phỏng Cloud Firestore không hoạt động với quy trình Xác thực Firebase thông thường. Thay vào đó, trong căn cứ hỏa lực thử nghiệm SDK, chúng tôi đã cung cấp initializeTestApp() phương pháp trong các rules-unit-testing thư viện, trong đó có một auth lĩnh vực. Tay cầm Firebase được tạo bằng phương pháp này sẽ hoạt động như thể nó đã được xác thực thành công dưới dạng bất kỳ thực thể nào bạn cung cấp. Nếu bạn vượt qua trong null , nó sẽ cư xử như một người dùng không được thẩm định ( auth != null quy tắc này sẽ thất bại, ví dụ).

Khắc phục sự cố đã biết

Khi sử dụng trình giả lập Cloud Firestore, bạn có thể gặp phải các sự cố đã biết sau đây. Làm theo hướng dẫn bên dưới để khắc phục mọi hành vi bất thường mà bạn đang gặp phải. Các ghi chú này được viết với thư viện kiểm tra đơn vị Quy tắc bảo mật, nhưng các phương pháp chung có thể áp dụng cho bất kỳ SDK Firebase nào.

Hành vi kiểm tra không nhất quán

Nếu các bài kiểm tra của bạn thỉnh thoảng đạt và không đạt, ngay cả khi không có bất kỳ thay đổi nào đối với các bài kiểm tra, bạn có thể cần xác minh rằng chúng được sắp xếp đúng theo trình tự. Hầu hết các tương tác với trình giả lập là không đồng bộ, vì vậy hãy kiểm tra kỹ xem tất cả mã không đồng bộ có được sắp xếp đúng trình tự hay không. Bạn có thể sửa chữa các chuỗi bởi một trong hai chaining lời hứa, hoặc sử dụng await ký hiệu tự do.

Đặc biệt, hãy xem lại các hoạt động không đồng bộ sau:

  • Thiết quy tắc an ninh, với, ví dụ, initializeTestEnvironment .
  • Đọc và ghi dữ liệu, với, ví dụ, db.collection("users").doc("alice").get() .
  • Khẳng định hoạt động, bao gồm assertSucceedsassertFails .

Các bài kiểm tra chỉ vượt qua lần đầu tiên bạn tải trình giả lập

Trình giả lập là trạng thái. Nó lưu trữ tất cả dữ liệu được ghi vào bộ nhớ, vì vậy mọi dữ liệu sẽ bị mất bất cứ khi nào trình giả lập tắt. Nếu bạn đang chạy nhiều thử nghiệm với cùng một id dự án, mỗi thử nghiệm có thể tạo ra dữ liệu có thể ảnh hưởng đến các thử nghiệm tiếp theo. Bạn có thể sử dụng bất kỳ phương pháp nào sau đây để bỏ qua hành vi này:

  • Sử dụng các ID dự án duy nhất cho mỗi thử nghiệm. Lưu ý rằng nếu bạn chọn để làm điều này, bạn sẽ cần phải gọi initializeTestEnvironment như một phần của mỗi bài kiểm tra; quy tắc chỉ được tải tự động cho ID dự án mặc định.
  • Cấu trúc lại các bài kiểm tra của bạn để chúng không tương tác với dữ liệu đã viết trước đó (ví dụ: sử dụng một bộ sưu tập khác nhau cho mỗi bài kiểm tra).
  • Xóa tất cả dữ liệu được ghi trong quá trình kiểm tra.

Thiết lập kiểm tra rất phức tạp

Khi thiết lập thử nghiệm, bạn có thể muốn sửa đổi dữ liệu theo cách mà Quy tắc bảo mật Cloud Firestore của bạn không thực sự cho phép. Nếu quy tắc của bạn đang làm thử nghiệm thiết lập phức tạp, hãy thử sử dụng RulesTestEnvironment.withSecurityRulesDisabled trong các bước thiết lập của bạn, vì vậy đọc và viết sẽ không kích hoạt PERMISSION_DENIED lỗi.

Sau đó, kiểm tra của bạn có thể thực hiện các hoạt động như một người dùng xác thực hoặc không được thẩm định sử dụng RulesTestEnvironment.authenticatedContextunauthenticatedContext tương ứng. Điều này cho phép bạn xác nhận rằng Quy tắc bảo mật Cloud Firestore của bạn cho phép / từ chối các trường hợp khác nhau một cách chính xác.