Firebase is back at Google I/O on May 10! Register now

Cấu trúc Quy tắc bảo mật Cloud Firestore

Sử dụng bộ sưu tập để sắp xếp ngăn nắp các trang Lưu và phân loại nội dung dựa trên lựa chọn ưu tiên của bạn.

Quy tắc bảo mật của Cloud Firestore cho phép bạn kiểm soát quyền truy cập vào tài liệu và bộ sưu tập trong cơ sở dữ liệu của mình. Cú pháp quy tắc linh hoạt cho phép bạn tạo các quy tắc khớp với bất kỳ thứ gì, từ tất cả các lần ghi vào toàn bộ cơ sở dữ liệu đến các thao tác trên một tài liệu cụ thể.

Hướng dẫn này mô tả cú pháp cơ bản và cấu trúc của các quy tắc bảo mật. Kết hợp cú pháp này với các điều kiện quy tắc bảo mật để tạo bộ quy tắc hoàn chỉnh.

Khai báo dịch vụ và cơ sở dữ liệu

Quy tắc bảo mật của Cloud Firestore luôn bắt đầu bằng khai báo sau:

service cloud.firestore {
  match /databases/{database}/documents {
    // ...
  }
}

Khai báo service cloud.firestore mở rộng phạm vi quy tắc cho Cloud Firestore, ngăn xung đột giữa Quy tắc bảo mật của Cloud Firestore và quy tắc cho các sản phẩm khác như Cloud Storage.

Khai báo match /databases/{database}/documents chỉ định rằng các quy tắc phải khớp với bất kỳ cơ sở dữ liệu Cloud Firestore nào trong dự án. Hiện tại mỗi dự án chỉ có một cơ sở dữ liệu duy nhất có tên (default) .

Quy tắc đọc/ghi cơ bản

Các quy tắc cơ bản bao gồm một câu lệnh match chỉ định đường dẫn tài liệu và biểu thức allow nêu chi tiết thời điểm cho phép đọc dữ liệu đã chỉ định:

service cloud.firestore {
  match /databases/{database}/documents {

    // Match any document in the 'cities' collection
    match /cities/{city} {
      allow read: if <condition>;
      allow write: if <condition>;
    }
  }
}

Tất cả các câu lệnh khớp phải trỏ đến tài liệu, không phải bộ sưu tập. Câu lệnh khớp có thể trỏ đến một tài liệu cụ thể, như trong match /cities/SF hoặc sử dụng ký tự đại diện để trỏ đến bất kỳ tài liệu nào trong đường dẫn đã chỉ định, như trong match /cities/{city} .

Trong ví dụ trên, câu lệnh so khớp sử dụng cú pháp ký tự đại diện {city} . Điều này có nghĩa là quy tắc áp dụng cho bất kỳ tài liệu nào trong bộ sưu tập cities , chẳng hạn như /cities/SF hoặc /cities/NYC . Khi các biểu thức allow trong câu lệnh đối sánh được đánh giá, biến city sẽ phân giải thành tên tài liệu thành phố, chẳng hạn như SF hoặc NYC .

hoạt động chi tiết

Trong một số trường hợp, sẽ rất hữu ích nếu bạn chia nhỏ readwrite thành các thao tác chi tiết hơn. Ví dụ: ứng dụng của bạn có thể muốn thực thi các điều kiện tạo tài liệu khác với điều kiện xóa tài liệu. Hoặc bạn có thể muốn cho phép đọc một tài liệu nhưng từ chối các truy vấn lớn.

Quy tắc read có thể được chia thành getlist , trong khi quy tắc write có thể được chia thành create , updatedelete :

service cloud.firestore {
  match /databases/{database}/documents {
    // A read rule can be divided into get and list rules
    match /cities/{city} {
      // Applies to single document read requests
      allow get: if <condition>;

      // Applies to queries and collection read requests
      allow list: if <condition>;
    }

    // A write rule can be divided into create, update, and delete rules
    match /cities/{city} {
      // Applies to writes to nonexistent documents
      allow create: if <condition>;

      // Applies to writes to existing documents
      allow update: if <condition>;

      // Applies to delete operations
      allow delete: if <condition>;
    }
  }
}

dữ liệu phân cấp

Dữ liệu trong Cloud Firestore được tổ chức thành các bộ sưu tập tài liệu và mỗi tài liệu có thể mở rộng hệ thống phân cấp thông qua các bộ sưu tập con. Điều quan trọng là phải hiểu cách các quy tắc bảo mật tương tác với dữ liệu phân cấp.

Xem xét tình huống trong đó mỗi tài liệu trong bộ sưu tập cities chứa một bộ sưu tập con landmarks . Các quy tắc bảo mật chỉ áp dụng tại đường dẫn phù hợp, do đó, các điều khiển truy cập được xác định trên bộ sưu tập cities không áp dụng cho bộ sưu tập con landmarks . Thay vào đó, hãy viết các quy tắc rõ ràng để kiểm soát quyền truy cập vào các bộ sưu tập con:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      allow read, write: if <condition>;

        // Explicitly define rules for the 'landmarks' subcollection
        match /landmarks/{landmark} {
          allow read, write: if <condition>;
        }
    }
  }
}

Khi lồng các câu lệnh match , đường dẫn của câu lệnh match bên trong luôn liên quan đến đường dẫn của câu lệnh match bên ngoài. Do đó, các bộ quy tắc sau đây là tương đương:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      match /landmarks/{landmark} {
        allow read, write: if <condition>;
      }
    }
  }
}
service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city}/landmarks/{landmark} {
      allow read, write: if <condition>;
    }
  }
}

Ký tự đại diện đệ quy

Nếu bạn muốn các quy tắc áp dụng cho một hệ thống phân cấp sâu tùy ý, hãy sử dụng cú pháp ký tự đại diện đệ quy, {name=**} . Ví dụ:

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Khi sử dụng cú pháp ký tự đại diện đệ quy, biến ký tự đại diện sẽ chứa toàn bộ đoạn đường dẫn phù hợp, ngay cả khi tài liệu nằm trong một tập hợp con được lồng sâu. Ví dụ: các quy tắc được liệt kê ở trên sẽ khớp với một tài liệu có tại /cities/SF/landmarks/coit_tower và giá trị của biến document sẽ là SF/landmarks/coit_tower .

Tuy nhiên, lưu ý rằng hành vi của các ký tự đại diện đệ quy phụ thuộc vào phiên bản quy tắc.

Phiên bản 1

Quy tắc bảo mật sử dụng phiên bản 1 theo mặc định. Trong phiên bản 1, các ký tự đại diện đệ quy khớp với một hoặc nhiều mục đường dẫn. Chúng không khớp với một đường dẫn trống, do đó match /cities/{city}/{document=**} khớp với các tài liệu trong bộ sưu tập con nhưng không khớp trong bộ sưu tập cities , trong khi match /cities/{document=**} khớp với cả hai tài liệu trong bộ sưu tập bộ sưu tập cities và bộ sưu tập con.

Các ký tự đại diện đệ quy phải xuất hiện ở cuối câu lệnh so khớp.

Phiên bản 2

Trong phiên bản 2 của quy tắc bảo mật, các ký tự đại diện đệ quy khớp với 0 hoặc nhiều mục đường dẫn. match/cities/{city}/{document=**} khớp với các tài liệu trong bất kỳ bộ sưu tập con nào cũng như các tài liệu trong bộ sưu tập cities .

Bạn phải chọn tham gia phiên bản 2 bằng cách thêm rules_version = '2'; ở đầu các quy tắc bảo mật của bạn:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the cities collection as well as any document
    // in a subcollection.
    match /cities/{city}/{document=**} {
      allow read, write: if <condition>;
    }
  }
}

Bạn có thể có nhiều nhất một ký tự đại diện đệ quy cho mỗi câu lệnh so khớp, nhưng trong phiên bản 2, bạn có thể đặt ký tự đại diện này ở bất kỳ đâu trong câu lệnh so khớp. Ví dụ:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the songs collection group
    match /{path=**}/songs/{song} {
      allow read, write: if <condition>;
    }
  }
}

Nếu bạn sử dụng truy vấn nhóm bộ sưu tập , bạn phải sử dụng phiên bản 2, xem bảo mật truy vấn nhóm bộ sưu tập .

Báo cáo đối sánh chồng chéo

Một tài liệu có thể khớp nhiều hơn một câu lệnh match . Trong trường hợp có nhiều biểu thức allow khớp với một yêu cầu, quyền truy cập được phép nếu bất kỳ điều kiện nào là true :

service cloud.firestore {
  match /databases/{database}/documents {
    // Matches any document in the 'cities' collection.
    match /cities/{city} {
      allow read, write: if false;
    }

    // Matches any document in the 'cities' collection or subcollections.
    match /cities/{document=**} {
      allow read, write: if true;
    }
  }
}

Trong ví dụ trên, tất cả các lần đọc và ghi vào bộ sưu tập cities sẽ được cho phép vì quy tắc thứ hai luôn true , mặc dù quy tắc đầu tiên luôn false .

Giới hạn quy tắc bảo mật

Khi bạn làm việc với các quy tắc bảo mật, hãy lưu ý các giới hạn sau:

Giới hạn Chi tiết
Số lượng lệnh exists() , get()getAfter() tối đa cho mỗi yêu cầu
  • 10 cho các yêu cầu tài liệu đơn và yêu cầu truy vấn.
  • 20 để đọc, giao dịch và ghi nhiều tài liệu. Giới hạn trước đó là 10 cũng áp dụng cho từng thao tác.

    Ví dụ: hãy tưởng tượng bạn tạo một yêu cầu ghi theo đợt với 3 thao tác ghi và các quy tắc bảo mật của bạn sử dụng 2 lệnh gọi truy cập tài liệu để xác thực mỗi lần ghi. Trong trường hợp này, mỗi lần ghi sử dụng 2 trong số 10 lệnh gọi truy cập và yêu cầu ghi theo lô sử dụng 6 trong số 20 lệnh gọi truy cập.

Vượt quá một trong hai giới hạn sẽ dẫn đến lỗi quyền bị từ chối.

Một số cuộc gọi truy cập tài liệu có thể được lưu trong bộ nhớ cache và các cuộc gọi được lưu trong bộ nhớ cache không được tính vào giới hạn.

Độ sâu match lồng nhau tối đa 10
Độ dài đường dẫn tối đa, trong các đoạn đường dẫn, được phép trong một tập hợp các câu lệnh match lồng nhau 100
Số lượng biến nắm bắt đường dẫn tối đa được phép trong một tập hợp các câu lệnh match lồng nhau 20
Độ sâu cuộc gọi chức năng tối đa 20
Số đối số hàm tối đa 7
Số liên kết biến let tối đa trên mỗi hàm 10
Số lần gọi hàm đệ quy hoặc theo chu kỳ tối đa 0 (không được phép)
Số biểu thức tối đa được đánh giá cho mỗi yêu cầu 1.000
Kích thước tối đa của một bộ quy tắc Bộ quy tắc phải tuân theo hai giới hạn kích thước:
  • giới hạn 256 KB đối với kích thước của nguồn văn bản bộ quy tắc được xuất bản từ bảng điều khiển Firebase hoặc từ CLI bằng firebase deploy .
  • giới hạn 250 KB đối với kích thước của bộ quy tắc đã biên dịch là kết quả khi Firebase xử lý nguồn và làm cho nó hoạt động ở mặt sau.

Bước tiếp theo