Bảo mật có thể là một trong những phần phức tạp nhất trong quá trình phát triển ứng dụng. Trong hầu hết các ứng dụng, nhà phát triển phải tạo và chạy một máy chủ xử lý việc xác thực (người dùng là ai) và uỷ quyền (những việc người dùng có thể làm).
Firebase Security Rules xoá 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. Hãy sử dụng hướng dẫn này để tìm hiểu thêm về cách áp dụng các quy tắc cho các yêu cầu đến.
Chọn một sản phẩm để tìm hiểu thêm về các quy tắc của sản phẩm đó.
Cloud Firestore
Cấu trúc cơ bản
Firebase Security Rules 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>>
}
}
Bạn cần hiểu rõ các khái niệm chính sau đây khi xây dựng 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à các phương thức bạn cho phép chạy. Các phương thức 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 quyền truy cập rộng rãi để đọc và ghi trên cơ sở dữ liệu hoặc đường dẫn bộ nhớ đã 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 yêu cầu nếu điều kiện đó đá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 ký tự đại diện
lồng nhau {name=**}
. Bạn phải sử dụng phiên bản 2 nếu dự định sử dụng cụm từ tìm kiếm nhóm bộ sưu tập. Bạn phải chọn sử dụng phiên bản 2 bằng cách đặt rules_version = '2';
làm dòng đầu tiên trong quy tắc bảo mật:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
Đường dẫn trùng khớp
Tất cả câu lệnh so khớp phải trỏ đến tài liệu chứ 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 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 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
.
Bộ sưu tập phụ trùng khớ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
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 đã so khớp, vì vậy, các chế độ kiểm soát quyền 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 bộ quy tắc sau đây tương đương với nhau:
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 áp dụng các quy tắc cho một hệ phân cấp sâu tuỳ ý, 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ộ phân đoạn đường dẫn khớp, ngay cả khi tài liệu nằm trong một tập hợp con lồng nhau 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 ở /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ử 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. Các biểu thức này không khớp với đườ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 bộ sưu tập cities
, trong khi match /cities/{document=**}
khớp với 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=**}
so khớp 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 sử dụng phiên bản 2 bằng cách thêm rules_version = '2';
vào đầ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 cụm từ tìm kiếm nhóm bộ sưu tập, bạn phải sử dụng phiên bản 2, hãy xem phần bảo mật cụm từ tìm kiếm nhóm bộ sưu tập.
Câu lệnh khớp trùng lặ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 bộ sưu tập cities
sẽ được cho phép vì quy tắc thứ hai luôn là true
, mặc dù quy tắc đầu tiên luôn là false
.
Giới hạn về 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 | Thông tin chi tiết |
---|---|
Số lệnh gọi exists() , get() và getAfter() tối đa 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 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 không tính vào hạn mức. |
Độ sâu tối đa của câu lệnh match lồng nhau |
10 |
Chiều dài đường dẫn tối đa, tính bằng các phân đ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 thu thập đường dẫn tối đa được phép trong một tập hợp
câu lệnh match lồng nhau |
20 |
Độ sâu lệnh gọi hàm tối đa | 20 |
Số lượng đối số hàm tối đa | 7 |
Số lượng liên kết biến let tối đa cho mỗi hàm |
10 |
Số lệnh gọi hàm đệ quy hoặc tuần hoàn tối đa | 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 | Bộ quy tắc phải tuân thủ hai giới hạn về kích thước:
|
Cloud Storage
Cấu trúc cơ bản
Firebase Security Rules 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>>
}
}
Bạn cần hiểu rõ các khái niệm chính sau đây khi xây dựng 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à các phương thức bạn cho phép chạy. Các phương thức 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 quyền truy cập rộng rãi để đọc và ghi trên cơ sở dữ liệu hoặc đường dẫn bộ nhớ đã 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 yêu cầu nếu điều kiện đó đánh giá là đúng.
Đường dẫn trùng khớp
Cloud Storage Security Rules match
đường dẫn tệp dùng để truy cập vào các tệp trong
Cloud Storage. Quy tắc có thể match
đường dẫn chính xác hoặc đường dẫn ký tự đại diện và quy tắc cũng có thể được lồng. Nếu không có quy tắc khớp nào cho phép phương thức yêu cầu hoặc điều kiện đánh giá là false
, thì yêu cầu sẽ bị từ chối.
Kết quả khớp 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>; }
Kết quả trùng khớp 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>; } }
Khớp với ký tự đại diện
Bạn cũng có thể sử dụng quy tắc để 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 duy nhất như profilePhoto.png
hoặc nhiều phân đoạn đường dẫn như images/profilePhoto.png
.
Bạn có thể tạo ký tự đại diện 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}
. Bạn có thể khai báo ký tự đại diện nhiều phân khúc bằng cách thêm =**
vào tên ký tự đại diện, chẳng hạ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, kết quả sẽ là OR
của kết quả tất cả các quy tắc đánh giá. Tức là nếu bất kỳ quy tắc nào mà tệp khớp đều đánh giá là true
, thì kết quả sẽ 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ỉ tuân theo kết quả của other_condition
.
Bạn có thể tham chiếu biến đại diện từ bên trong match
cung cấp tên tệp hoặc uỷ quyền đường dẫn:
// Another way to restrict the name of a file match /images/{imageId} { allow read: if imageId == "profilePhoto.png"; }
Cloud Storage Security Rules không tạo hiệu ứng lũy thừa và các 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á
Các hoạt động tải lên, tải xuống, thay đổi siêu dữ liệu và xoá được đánh giá bằng cách sử dụng request
được gửi đến 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 điểm 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 đưa vào.
Đối tượng request
cũng chứa mã nhận dạng duy nhất của người dùng và tải trọng Firebase Authentication trong đối tượng request.auth
. Chúng tôi sẽ giải thích thêm về đối tượng này 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 | Loại | Mô tả |
---|---|---|
auth |
map<string, string> | Khi người dùng đăng nhập, hãy cung cấp uid , mã nhận dạng duy nhất của người dùng và token , một bản đồ của các thông báo xác nhận JWT Firebase Authentication. Nếu không, giá trị sẽ là null . |
params |
map<string, string> | Bản đồ chứa các tham số truy vấn của yêu cầu. |
path |
đường dẫn | path đại diện cho đường dẫn mà yêu cầu đang được thực hiện. |
resource |
map<string, string> | 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 thể hiện thời gian máy chủ đánh giá yêu cầu. |
Đánh giá tài nguyên
Khi đánh giá các quy tắc, bạn cũng nê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 xoá. Đ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ó một số loại nội dung nhất định hoặc chỉ xoá các tệp có kích thước lớn hơn một kích thước nhất định.
Firebase Security Rules cho Cloud Storage cung cấp siêu dữ liệu tệp trong đối tượng resource
. Đối tượng này chứa các cặp khoá/giá trị của siêu dữ liệu xuất hiện trong đối tượng Cloud Storage. Bạn có thể kiểm tra các thuộc tính này trên các yêu cầu read
hoặc write
để đảm bảo tính toàn vẹn của dữ liệu.
Trên 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à xoá), ngoài đối tượng resource
chứa siêu dữ liệu tệp cho tệp hiện có tại đường dẫn yêu cầu, bạn cũng có thể sử dụng đối tượng request.resource
chứa một tập hợp con siêu dữ liệu tệp cần ghi nếu được phép ghi. 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 quy tắc ràng buộc của ứng dụng, chẳng hạn như loại tệp 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 | Loại | Mô tả |
---|---|---|
name |
chuỗi | Tên đầy đủ của đối tượng |
bucket |
chuỗi | Tên của bộ chứa 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 | Tạo 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 điểm tạo đối tượng. |
updated |
dấu thời gian | Dấu thời gian thể hiện thời điểm gần đây nhất một đối tượng được cập nhật. |
md5Hash |
chuỗi | Hàm băm MD5 của đối tượng. |
crc32c |
chuỗi | Hàm băm crc32c của đối tượng. |
etag |
chuỗi | Etag liên kết với đối tượng này. |
contentDisposition |
chuỗi | Vị trí lưu trữ nội dung liên kết với đối tượng này. |
contentEncoding |
chuỗi | Mã hoá nội dung được liên kết với đối tượng này. |
contentLanguage |
chuỗi | Ngôn ngữ nội dung liên kết với đối tượng này. |
contentType |
chuỗi | Loại nội dung liên kết với đối tượng này. |
metadata |
map<string, string> | Cặp khoá/giá trị của siêu dữ liệu tuỳ chỉnh bổ sung do nhà phát triển chỉ định. |
request.resource
chứa tất cả các thuộc tính này ngoại trừ generation
, metageneration
, etag
, timeCreated
và updated
.
Giới hạn của 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 | Thông tin chi tiết |
---|---|
Số lệnh gọi firestore.exists() và firestore.get() tối đa cho mỗi yêu cầu |
2 đối với yêu cầu về một tài liệu và yêu cầu truy vấn. Nếu vượt quá giới hạn này, bạn sẽ gặp lỗi từ chối cấp quyền. Các lệnh gọi truy cập vào cùng một 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 các giới hạn. |
Ví dụ đầy đủ
Khi kết hợp tất cả các quy tắc này, 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 } } } }
Realtime Database
Cấu trúc cơ bản
Trong Realtime Database, Firebase Security Rules bao gồm các biểu thức giống JavaScript có trong tài liệu JSON.
Các hàm này 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 phần tử cơ bản trong quy tắc:
- Đường dẫn: Vị trí cơ sở dữ liệu. Thao tác này phản ánh cấu trúc JSON của cơ sở dữ liệu.
- Yêu cầu: Đây là các phương thức mà quy tắc sử dụng để cấp quyền truy cập. Quy tắc
read
vàwrite
cấp quyền đọc và ghi rộng rãi, trong khi quy tắcvalidate
đóng vai trò là quy trình xác minh phụ để cấp quyền truy cập dựa trên dữ liệu đến hoặc hiện có. - Điều kiện: Điều kiện cho phép một yêu cầu nếu điều kiện đó đánh giá là đúng.
Cách áp dụng quy tắc cho đường dẫn
Trong Realtime Database, Rules áp dụng theo nguyên tử, nghĩa là các quy tắc ở nút mẹ cấp cao hơn sẽ ghi đè các quy tắ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 mẹ. Bạn không thể tinh chỉnh hoặc thu hồi quyền truy cập ở một đường dẫn sâu hơn trong cấu trúc cơ sở dữ liệu nếu bạn đã cấp quyền truy cập đó cho một trong các đường dẫn gốc.
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 đọc /bar/
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ì quyền truy cập không thể bị thu hồi theo đường dẫn con.
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 triển khai các đặc quyền truy cập rất phức tạp với ít nỗ lực nhất. Điều này đặc biệt hữu ích đối với chế độ bảo mật dựa trên người dùng.
Tuy nhiên, quy tắc .validate
không có hiệu lực lũy tiến. Tất cả các quy tắc xác thực phải được đáp ứng ở tất cả các cấp của hệ phân cấp để cho phép ghi.
Ngoài ra, vì các quy tắc không áp dụng lại cho đường dẫn gốc, nên thao tác đọc hoặc ghi sẽ 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 có thể truy cập vào mọi đường dẫn con bị ảnh hưởng, việc đọc ở vị trí mẹ sẽ hoàn toàn không thành công. Hãy xem xét cấu trúc sau:
{ "rules": { "records": { "rec1": { ".read": true }, "rec2": { ".read": false } } } }
Nếu không hiểu rằng các quy tắc được đánh giá một cách nguyên tử, có thể bạn sẽ thấy việc tìm nạp đường dẫn /records/
sẽ trả về rec1
nhưng 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 });
Objective-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 }];
Swift
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 }); });
Kiến trúc chuyển trạng thái đại diện (REST)
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/
, nên thao tác này sẽ gửi lỗi PERMISSION_DENIED
. Nếu đánh giá quy tắc này trong trình mô phỏng bảo mật trong bảng điều khiển Firebase, chúng ta 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 này 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 xin lưu ý rằng quy tắc cho rec1
chưa bao giờ được đánh giá vì quy tắc này không nằm trong đường dẫn mà 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 rec1
:
JavaScript
var db = firebase.database(); db.ref("records/rec1").once("value", function(snap) { // SUCCESS! }, function(err) { // error callback is not called });
Objective-C
FIRDatabaseReference *ref = [[FIRDatabase database] reference]; [[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) { // SUCCESS! }];
Swift
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 } });
Kiến trúc chuyển trạng thái đại diện (REST)
curl https://docs-examples.firebaseio.com/rest/records/rec1 # SUCCESS!
Biến vị trí
Realtime Database Rules hỗ trợ biến $location
để so khớp các phân đoạn đường dẫn. Sử dụng tiền tố $
ở đầu đoạn đường dẫn để so khớp quy tắc với mọi nút con 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 tên đường dẫn không đổi.
{
"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 }
}
}
}