Bảo mật có thể là một trong những phần phức tạp nhất của câu đố phát triển ứng dụng. Trong hầu hết các ứng dụng, nhà phát triển phải xây dựng và chạy một máy chủ xử lý xác thực (người dùng là ai) và ủy quyền (người dùng có thể làm gì).
Quy tắc bảo mật Firebase loại bỏ lớp giữa (máy chủ) và cho phép bạn chỉ định quyền dựa trên đường dẫn cho các ứng dụng khách kết nối trực tiếp với dữ liệu của bạn. Sử dụng hướng dẫn này để tìm hiểu thêm về cách các quy tắc được áp dụng cho các yêu cầu gửi đến.
Chọn một sản phẩm để tìm hiểu thêm về các quy tắc của nó.
Cửa hàng lửa trên đám mây
Cấu trúc cơ bản
Quy tắc bảo mật Firebase trong Cloud Firestore và Cloud Storage sử dụng cấu trúc và cú pháp sau:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Các khái niệm chính sau đây rất quan trọng để hiểu khi bạn xây dựng các quy tắc:
- Yêu cầu: Phương thức hoặc các phương thức được gọi trong câu lệnh
allow
. Đây là những phương pháp bạn đang cho phép chạy. Các phương pháp tiêu chuẩn là:get
,list
,create
,update
vàdelete
. Các phương thức thuận tiệnread
vàwrite
cho phép truy cập đọc và ghi rộng rãi trên cơ sở dữ liệu hoặc đường dẫn lưu trữ được chỉ định. - Đường dẫn: Cơ sở dữ liệu hoặc vị trí lưu trữ, được biểu thị dưới dạng đường dẫn URI.
- Quy tắc: Câu lệnh
allow
, bao gồm một điều kiện cho phép một yêu cầu nếu nó được đánh giá là đúng.
Quy tắc bảo mật phiên bản 2
Kể từ tháng 5 năm 2019, phiên bản 2 của quy tắc bảo mật Firebase hiện đã có. Phiên bản 2 của quy tắc thay đổi hành vi của các ký tự đại diện đệ quy {name=**}
. Bạn phải sử dụng phiên bản 2 nếu bạn định sử dụng truy vấn nhóm bộ sưu tập . Bạn phải chọn tham gia phiên bản 2 bằng cách tạo rules_version = '2';
dòng đầu tiên trong quy tắc bảo mật của bạn:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
đường dẫn phù hợp
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
.
Bộ sưu tập con phù hợ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=**}
:
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() và getAfter() tối đa cho mỗi yêu cầu |
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:
|
Lưu trữ đám mây
Cấu trúc cơ bản
Quy tắc bảo mật Firebase trong Cloud Firestore và Cloud Storage sử dụng cấu trúc và cú pháp sau:
service <<name>> {
// Match the resource path.
match <<path>> {
// Allow the request if the following conditions are true.
allow <<methods>> : if <<condition>>
}
}
Các khái niệm chính sau đây rất quan trọng để hiểu khi bạn xây dựng các quy tắc:
- Yêu cầu: Phương thức hoặc các phương thức được gọi trong câu lệnh
allow
. Đây là những phương pháp bạn đang cho phép chạy. Các phương pháp tiêu chuẩn là:get
,list
,create
,update
vàdelete
. Các phương thức thuận tiệnread
vàwrite
cho phép truy cập đọc và ghi rộng rãi trên cơ sở dữ liệu hoặc đường dẫn lưu trữ được chỉ định. - Đường dẫn: Cơ sở dữ liệu hoặc vị trí lưu trữ, được biểu thị dưới dạng đường dẫn URI.
- Quy tắc: Câu lệnh
allow
, bao gồm một điều kiện cho phép một yêu cầu nếu nó được đánh giá là đúng.
đường dẫn phù hợp
Quy tắc bảo mật lưu trữ đám mây match
đường dẫn tệp được sử dụng để truy cập tệp trong Lưu trữ đám mây. Các quy tắc có thể match
các đường dẫn chính xác hoặc đường dẫn ký tự đại diện và các quy tắc cũng có thể được lồng vào nhau. Nếu không có quy tắc đối sánh nào cho phép một phương thức yêu cầu hoặc điều kiện đánh giá là false
, yêu cầu sẽ bị từ chối.
trận đấu chính xác
// Exact match for "images/profilePhoto.png" match /images/profilePhoto.png { allow write: if <condition>; } // Exact match for "images/croppedProfilePhoto.png" match /images/croppedProfilePhoto.png { allow write: if <other_condition>; }
các trận đấu lồng nhau
// Partial match for files that start with "images" match /images { // Exact match for "images/profilePhoto.png" match /profilePhoto.png { allow write: if <condition>; } // Exact match for "images/croppedProfilePhoto.png" match /croppedProfilePhoto.png { allow write: if <other_condition>; } }
trận đấu ký tự đại diện
Các quy tắc cũng có thể được sử dụng để match
một mẫu bằng ký tự đại diện. Ký tự đại diện là một biến được đặt tên đại diện cho một chuỗi đơn, chẳng hạn như profilePhoto.png
hoặc nhiều phân đoạn đường dẫn, chẳng hạn như images/profilePhoto.png
.
Ký tự đại diện được tạo bằng cách thêm dấu ngoặc nhọn xung quanh tên ký tự đại diện, chẳng hạn như {string}
. Có thể khai báo ký tự đại diện nhiều đoạn bằng cách thêm =**
vào tên ký tự đại diện, như {path=**}
:
// Partial match for files that start with "images" match /images { // Exact match for "images/*" // e.g. images/profilePhoto.png is matched match /{imageId} { // This rule only matches a single path segment (*) // imageId is a string that contains the specific segment matched allow read: if <condition>; } // Exact match for "images/**" // e.g. images/users/user:12345/profilePhoto.png is matched // images/profilePhoto.png is also matched! match /{allImages=**} { // This rule matches one or more path segments (**) // allImages is a path that contains all segments matched allow read: if <other_condition>; } }
Nếu nhiều quy tắc khớp với một tệp, thì kết quả là OR
của kết quả đánh giá tất cả các quy tắc. Nghĩa là, nếu bất kỳ quy tắc nào mà tệp khớp với giá trị là true
, thì kết quả là true
.
Trong các quy tắc trên, tệp "images/profilePhoto.png" có thể được đọc nếu condition
hoặc other_condition
đánh giá là đúng, trong khi tệp "images/users/user:12345/profilePhoto.png" chỉ phụ thuộc vào kết quả của other_condition
.
Một biến ký tự đại diện có thể được tham chiếu từ trong match
cung cấp tên tệp hoặc ủy quyền đường dẫn:
// Another way to restrict the name of a file match /images/{imageId} { allow read: if imageId == "profilePhoto.png"; }
Quy tắc bảo mật lưu trữ đám mây không phân tầng và quy tắc chỉ được đánh giá khi đường dẫn yêu cầu khớp với đường dẫn có quy tắc được chỉ định.
Yêu cầu đánh giá
Tải lên, tải xuống, thay đổi siêu dữ liệu và xóa được đánh giá bằng cách sử dụng request
được gửi tới Cloud Storage. Biến request
chứa đường dẫn tệp nơi yêu cầu đang được thực hiện, thời gian nhận được yêu cầu và giá trị resource
mới nếu yêu cầu là ghi. Tiêu đề HTTP và trạng thái xác thực cũng được bao gồm.
Đối tượng request
cũng chứa ID duy nhất của người dùng và tải trọng Xác thực Firebase trong đối tượng request.auth
, sẽ được giải thích thêm trong phần Xác thực của tài liệu.
Dưới đây là danh sách đầy đủ các thuộc tính trong đối tượng request
:
Tài sản | Kiểu | Sự miêu tả |
---|---|---|
auth | bản đồ<chuỗi, chuỗi> | Khi người dùng đăng nhập, hãy cung cấp uid , ID duy nhất của người dùng và token , bản đồ các xác nhận quyền sở hữu JWT của Firebase Authentication. Nếu không, nó sẽ là null . |
params | bản đồ<chuỗi, chuỗi> | Bản đồ chứa các tham số truy vấn của yêu cầu. |
path | con đường | path đại diện cho đường dẫn mà yêu cầu đang được thực hiện. |
resource | bản đồ<chuỗi, chuỗi> | Giá trị tài nguyên mới, chỉ xuất hiện trên các yêu cầu write . |
time | dấu thời gian | Dấu thời gian biểu thị thời gian máy chủ yêu cầu được đánh giá tại. |
đánh giá tài nguyên
Khi đánh giá các quy tắc, bạn cũng có thể muốn đánh giá siêu dữ liệu của tệp đang được tải lên, tải xuống, sửa đổi hoặc xóa. Điều này cho phép bạn tạo các quy tắc phức tạp và mạnh mẽ để thực hiện những việc như chỉ cho phép tải lên các tệp có loại nội dung nhất định hoặc chỉ xóa các tệp có kích thước lớn hơn một kích thước nhất định.
Quy tắc bảo mật Firebase cho Lưu trữ đám mây cung cấp siêu dữ liệu tệp trong đối tượng resource
, chứa các cặp khóa/giá trị của siêu dữ liệu xuất hiện trong đối tượng Lưu trữ đám mây. Các thuộc tính này có thể được kiểm tra theo yêu cầu read
hoặc write
để đảm bảo tính toàn vẹn của dữ liệu.
Đối với các yêu cầu write
(chẳng hạn như tải lên, cập nhật siêu dữ liệu và xóa), ngoài đối tượng tài nguyên chứa resource
dữ liệu tệp cho tệp hiện đang tồn tại ở đường dẫn yêu cầu, bạn cũng có khả năng sử dụng đối tượng request.resource
, trong đó chứa một tập hợp con của siêu dữ liệu tệp sẽ được ghi nếu việc ghi được cho phép. Bạn có thể sử dụng hai giá trị này để đảm bảo tính toàn vẹn của dữ liệu hoặc thực thi các ràng buộc của ứng dụng chẳng hạn như loại hoặc kích thước tệp.
Dưới đây là danh sách đầy đủ các thuộc tính trong đối tượng resource
:
Tài sản | Kiểu | Sự miêu tả |
---|---|---|
name | sợi dây | Tên đầy đủ của đối tượng |
bucket | sợi dây | Tên của vùng chứa đối tượng này. |
generation | int | Quá trình tạo đối tượng Google Cloud Storage của đối tượng này. |
metageneration | int | Siêu dữ liệu đối tượng Google Cloud Storage của đối tượng này. |
size | int | Kích thước của đối tượng tính bằng byte. |
timeCreated | dấu thời gian | Dấu thời gian biểu thị thời gian một đối tượng được tạo. |
updated | dấu thời gian | Dấu thời gian biểu thị thời gian một đối tượng được cập nhật lần cuối. |
md5Hash | sợi dây | Hàm băm MD5 của đối tượng. |
crc32c | sợi dây | Hàm băm crc32c của đối tượng. |
etag | sợi dây | etag được liên kết với đối tượng này. |
contentDisposition | sợi dây | Bố cục nội dung được liên kết với đối tượng này. |
contentEncoding | sợi dây | Mã hóa nội dung được liên kết với đối tượng này. |
contentLanguage | sợi dây | Ngôn ngữ nội dung được liên kết với đối tượng này. |
contentType | sợi dây | Loại nội dung được liên kết với đối tượng này. |
metadata | bản đồ<chuỗi, chuỗi> | Các cặp khóa/giá trị của siêu dữ liệu tùy chỉnh bổ sung do nhà phát triển chỉ định. |
request.resource
chứa tất cả những thứ này ngoại trừ generation
, metageneration
, etag
, timeCreated
và updated
.
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ần gọi firestore.exists() và firestore.get() tối đa cho mỗi yêu cầu | 2 cho các yêu cầu tài liệu đơn và yêu cầu truy vấn. Vượt quá giới hạn này dẫn đến lỗi quyền bị từ chối. Các cuộc gọi truy cập vào cùng một 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. |
Ví dụ đầy đủ
Kết hợp tất cả lại với nhau, bạn có thể tạo một ví dụ đầy đủ về các quy tắc cho giải pháp lưu trữ hình ảnh:
service firebase.storage { match /b/{bucket}/o { match /images { // Cascade read to any image type at any path match /{allImages=**} { allow read; } // Allow write files to the path "images/*", subject to the constraints: // 1) File is less than 5MB // 2) Content type is an image // 3) Uploaded content type matches existing content type // 4) File name (stored in imageId wildcard variable) is less than 32 characters match /{imageId} { allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*') && request.resource.contentType == resource.contentType && imageId.size() < 32 } } } }
Cơ sở dữ liệu thời gian thực
Cấu trúc cơ bản
Trong Cơ sở dữ liệu thời gian thực, Quy tắc bảo mật Firebase bao gồm các biểu thức giống như JavaScript có trong tài liệu JSON.
Họ sử dụng cú pháp sau:
{
"rules": {
"<<path>>": {
// Allow the request if the condition for each method is true.
".read": <<condition>>,
".write": <<condition>>,
".validate": <<condition>>
}
}
}
Có ba yếu tố cơ bản trong quy tắc:
- Đường dẫn: Vị trí cơ sở dữ liệu. Điều này phản ánh cấu trúc JSON của cơ sở dữ liệu của bạn.
- Yêu cầu: Đây là những phương thức mà quy tắc sử dụng để cấp quyền truy cập. Các quy tắc
read
vàwrite
quyền truy cập đọc và ghi rộng rãi, trong khi các quy tắcvalidate
hoạt động như một xác minh thứ cấp để cấp quyền truy cập dựa trên dữ liệu đến hoặc dữ liệu hiện có. - Điều kiện: Điều kiện cho phép một yêu cầu nếu nó được đánh giá là đúng.
Cách quy tắc áp dụng cho đường dẫn
Trong Cơ sở dữ liệu thời gian thực, Quy tắc áp dụng nguyên tử, nghĩa là các quy tắc ở các nút gốc cấp cao hơn sẽ ghi đè các quy tắc ở các nút con chi tiết hơn và các quy tắc ở nút sâu hơn không thể cấp quyền truy cập vào đường dẫn gốc. Bạn không thể tinh chỉnh hoặc thu hồi quyền truy cập ở đường dẫn sâu hơn trong cấu trúc cơ sở dữ liệu của mình nếu bạn đã cấp quyền truy cập đó cho một trong các đường dẫn chính.
Hãy xem xét các quy tắc sau:
{ "rules": { "foo": { // allows read to /foo/* ".read": "data.child('baz').val() === true", "bar": { // ignored, since read was allowed already ".read": false } } } }
Cấu trúc bảo mật này cho phép /bar/
được đọc bất cứ khi nào /foo/
chứa một baz
con có giá trị true
. Quy tắc ".read": false
trong /foo/bar/
không có hiệu lực ở đây, vì đường dẫn con không thể thu hồi quyền truy cập.
Mặc dù có vẻ không trực quan ngay lập tức, nhưng đây là một phần mạnh mẽ của ngôn ngữ quy tắc và cho phép thực hiện các đặc quyền truy cập rất phức tạp với nỗ lực tối thiểu. Điều này đặc biệt hữu ích cho bảo mật dựa trên người dùng .
Tuy nhiên, quy tắc .validate
không xếp tầng. Tất cả các quy tắc xác thực phải được thỏa mãn ở tất cả các cấp của hệ thống phân cấp để cho phép ghi.
Ngoài ra, do các quy tắc không áp dụng ngược lại cho đường dẫn gốc nên thao tác đọc hoặc ghi không thành công nếu không có quy tắc tại vị trí được yêu cầu hoặc tại vị trí gốc cấp quyền truy cập. Ngay cả khi mọi đường dẫn con bị ảnh hưởng đều có thể truy cập được, thì việc đọc tại vị trí gốc sẽ thất bại hoàn toàn. Hãy xem xét cấu trúc này:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
Nếu không hiểu rằng các quy tắc được đánh giá nguyên tử, có vẻ như việc tìm nạp đường dẫn /records/
sẽ trả về rec1
chứ không phải rec2
. Tuy nhiên, kết quả thực tế là một lỗi:
JavaScript
var db = firebase.database(); db.ref("records").once("value", function(snap) { // success method is not called }, function(err) { // error callback triggered with PERMISSION_DENIED });
Mục tiêu-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[_ref child:@"records"] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // success block is not called } withCancelBlock:^(NSError * _Nonnull error) { // cancel block triggered with PERMISSION_DENIED }];
Nhanh
var ref = FIRDatabase.database().reference() ref.child("records").observeSingleEventOfType(.Value, withBlock: { snapshot in // success block is not called }, withCancelBlock: { error in // cancel block triggered with PERMISSION_DENIED })
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // success method is not called } @Override public void onCancelled(FirebaseError firebaseError) { // error callback triggered with PERMISSION_DENIED }); });
NGHỈ NGƠI
curl https://docs-examples.firebaseio.com/rest/records/ # response returns a PERMISSION_DENIED error
Vì thao tác đọc tại /records/
là nguyên tử và không có quy tắc đọc nào cấp quyền truy cập vào tất cả dữ liệu trong /records/
, điều này sẽ gây ra lỗi PERMISSION_DENIED
. Nếu chúng tôi đánh giá quy tắc này trong trình giả lập bảo mật trong bảng điều khiển Firebase của mình, chúng tôi có thể thấy rằng thao tác đọc đã bị từ chối:
Attempt to read /records with auth=Success(null) / /records No .read rule allowed the operation. Read was denied.
Thao tác bị từ chối vì không có quy tắc đọc nào cho phép truy cập vào đường dẫn /records/
, nhưng lưu ý rằng quy tắc cho rec1
chưa bao giờ được đánh giá vì nó không nằm trong đường dẫn chúng tôi yêu cầu. Để tìm nạp rec1
, chúng ta cần truy cập trực tiếp vào nó:
JavaScript
var db = firebase.database(); db.ref("records/rec1").once("value", function(snap) { // SUCCESS! }, function(err) { // error callback is not called });
Mục tiêu-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Nhanh
var ref = FIRDatabase.database().reference() ref.child("records/rec1").observeSingleEventOfType(.Value, withBlock: { snapshot in // SUCCESS! })
Java
FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference ref = database.getReference("records/rec1"); ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot snapshot) { // SUCCESS! } @Override public void onCancelled(FirebaseError firebaseError) { // error callback is not called } });
NGHỈ NGƠI
curl https://docs-examples.firebaseio.com/rest/records/rec1 # SUCCESS!
biến vị trí
Quy tắc cơ sở dữ liệu thời gian thực hỗ trợ biến $location
để khớp với các đoạn đường dẫn. Sử dụng tiền tố $
phía trước đoạn đường dẫn của bạn để khớp quy tắc của bạn với bất kỳ nút con nào dọc theo đường dẫn.
{
"rules": {
"rooms": {
// This rule applies to any child of /rooms/, the key for each room id
// is stored inside $room_id variable for reference
"$room_id": {
"topic": {
// The room's topic can be changed if the room id has "public" in it
".write": "$room_id.contains('public')"
}
}
}
}
}
Bạn cũng có thể sử dụng $variable
song song với các tên đường dẫn cố định.
{
"rules": {
"widget": {
// a widget can have a title or color attribute
"title": { ".validate": true },
"color": { ".validate": true },
// but no other child paths are allowed
// in this case, $other means any key excluding "title" and "color"
"$other": { ".validate": false }
}
}
}