Cloud Firestore Security Rules cho phép bạn kiểm soát quyền truy cập vào các 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 phù hợp với mọi thứ, từ tất cả các thao tác ghi vào toàn bộ cơ sở dữ liệu cho đế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 và cấu trúc cơ bản 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 của 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
Cloud Firestore Security Rules luôn bắt đầu bằng nội dung khai báo sau:
service cloud.firestore {
match /databases/{database}/documents {
// ...
}
}
Khai báo service cloud.firestore
sẽ giới hạn các quy tắc trong Cloud Firestore, ngăn chặn xung đột giữa Cloud Firestore Security Rules và các quy tắc cho những 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 mọi cơ sở dữ liệu Cloud Firestore 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 là (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à một biểu thức allow
nêu chi tiết thời điểm được 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âu lệnh khớp đều phải trỏ đến các tài liệu chứ không phải các bộ sưu tập. Một câu lệnh so 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 này áp dụng cho mọi tài liệu 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 so khớp đượ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, bạn nên chia read
và write
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 khác nhau đối với việc tạo tài liệu so với việc xoá 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.
Bạn có thể chia quy tắc read
thành get
và list
, còn quy tắc write
có thể chia thành create
, update
và delete
:
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 sắp xếp 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ệ phân cấp thông qua các bộ sưu tập con. Điều quan trọng là bạn 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.
Hãy xem xét trường hợp mỗi tài liệu trong tập hợp cities
đều chứa một tập hợp con landmarks
. Các quy tắc bảo mật chỉ áp dụng tại đường dẫn trùng khớp, vì vậy, các quyền kiểm soát truy cập được xác định trên tập hợp cities
sẽ không áp dụng cho tập hợ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 tương ứng với đường dẫn của câu lệnh match
bên ngoài. Do đó, các nhóm 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ệ phân cấp có độ sâu tuỳ ý, 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ộ phân đoạn đường dẫn khớp, ngay cả khi tài liệu nằm trong một bộ sưu tập con được lồng sâu. Ví dụ: các quy tắc nêu trên sẽ khớp với một tài liệu nằm tại /cities/SF/landmarks/coit_tower
và giá trị của biến document
sẽ là SF/landmarks/coit_tower
.
Tuy nhiên, hãy lưu ý rằng hành vi của ký tự đại diện đệ quy phụ thuộc vào phiên bản quy tắc.
Phiên bản 1
Theo mặc định, các quy tắc bảo mật sẽ sử dụng phiên bản 1. Trong phiên bản 1, 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, vì vậy 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 với các tài liệu trong bộ sưu tập cities
, trong khi match /cities/{document=**}
khớp với cả các tài liệu trong bộ sưu tập cities
và bộ sưu tập con.
Ký tự đại diện đệ quy phải nằm ở 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, 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 mọi bộ sưu tập con cũng như các tài liệu trong bộ sưu tập cities
.
Bạn phải chọn sử dụng phiên bản 2 bằng cách thêm rules_version = '2';
ở đầu quy tắc bảo mật:
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ó tối đa 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ỳ vị trí nào 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 sử dụng truy vấn nhóm tập hợp, bạn phải sử dụng phiên bản 2, hãy xem phần bảo mật truy vấn nhóm tập hợp.
Câu lệnh trùng khớp
Một tài liệu có thể khớp với nhiều câu lệnh match
. Trong trường hợp nhiều biểu thức allow
khớp với một yêu cầu, quyền truy cập sẽ được cho 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 thao tác đọc và ghi vào tập hợp cities
sẽ được cho phép vì quy tắc thứ hai luôn là true
, ngay cả khi quy tắc đầu tiên luôn là false
.
Hạn mức quy tắc bảo mật
Khi làm việc với các quy tắc bảo mật, hãy lưu ý những giới hạn sau:
Giới hạn | Thông tin chi tiết |
---|---|
Số lượng lệnh gọi tối đa cho exists() , get() và getAfter() cho mỗi yêu cầu |
Nếu vượt quá một trong hai giới hạn này, bạn sẽ gặp lỗi bị từ chối cấp quyền. Một số lệnh gọi truy cập tài liệu có thể được lưu vào bộ nhớ đệm và các lệnh gọi được lưu vào bộ nhớ đệm sẽ không được tính vào giới hạn. |
Độ sâu tối đa của câu lệnh match được lồng |
10 |
Độ dài đường dẫn tối đa (tính bằng phân đoạn đường dẫn) được phép trong một nhóm câu lệnh match lồng nhau |
100 |
Số lượng biến chụp đường dẫn tối đa được phép trong một nhóm câu lệnh match lồng nhau |
20 |
Độ sâu tối đa của lệnh gọi hàm | 20 |
Số lượng đối số hàm tối đa | 7 |
Số lượng tối đa let liên kết biến cho mỗi hàm |
10 |
Số lượng tối đa các lệnh gọi hàm đệ quy hoặc hàm theo chu kỳ | 0 (không được phép) |
Số lượng 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 | Tập hợp quy tắc phải tuân thủ 2 giới hạn về kích thước:
|