Cách hoạt động của Quy tắc bảo mật

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 xây dựng và chạy một máy chủ xử lý quy trình 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 phương thức dựa trên đường dẫn quyề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 xem hướng dẫn này để tìm hiểu thêm về cách áp dụng quy tắc cho các yêu cầu sắp tới.

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 FirestoreCloud Storage sử dụng cấu trúc sau và cú pháp:

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 bạn cần hiểu rõ 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à mà bạn cho phép chạy. Các phương thức chuẩn là: get, list, create, updatedelete. Phương thức readwrite tiện lợi cho phép truy cập đọc và ghi trên đường dẫn lưu trữ hoặc cơ sở dữ liệu đượ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 nếu nó có kết quả 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 các quy tắc bảo mật Firebase sẵn có. Phiên bản 2 của các quy tắc này thay đổi hành vi của toán tử đệ quy ký tự đại diện {name=**}. Bạn phải sử dụng phiên bản 2 nếu định sử dụng truy vấn nhóm thu thập. Bạn phải chọn tham gia phiên bản 2 bằng cách đặt rules_version = '2'; làm dòng đầu tiên trong hoạt động bảo mật quy tắc:

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {

Đường dẫn phù hợ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. Trận đấu câu lệnh 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 tài liệu bất kỳ trong đường dẫn được 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}. Tức là quy tắc này áp dụng cho mọi tài liệu trong tập hợp cities, chẳng hạn như /cities/SF hoặc /cities/NYC. Khi biểu thức allow trong câu lệnh khớp là được đánh giá, biến city sẽ phân giải thành tên tài liệu của thành phố, chẳng hạn như SF hoặc NYC.

Tập hợp con trùng khớp

Dữ liệu trong Cloud Firestore được sắp xếp thành các tập hợp tài liệu và mỗi tập hợp có thể mở rộng hệ phân cấp thông qua các tập hợp con. Điều quan trọng là 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 tình huống mà mỗi tài liệu trong tập hợp cities chứa 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 đã 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 tập hợ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. Bộ quy tắc sau do đó 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 á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 đạ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 được liệt kê ở trên sẽ phù hợp 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, lưu ý rằng hành vi của ký tự đại diện đệ quy phụ thuộc vào 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. Chúng 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 tập hợp con nhưng không có trong tập hợp cities, trong khi match /cities/{document=**} khớp với cả hai tài liệu trong tập hợp cities và các tập hợ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 các quy tắc bảo mật, các ký tự đại diện đệ quy khớp với đường dẫn từ 0 trở lên mục. match/cities/{city}/{document=**} khớp với tài liệu trong bất kỳ các tập hợp con cũng như tài liệu trong tập hợ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 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ó tối đa một ký tự đại diện đệ quy cho mỗi câu lệnh so khớp (nhưng phải có trong phiên bản) 2, bạn có thể đặt ký tự đại diện này ở bất cứ đâ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 sử dụng truy vấn nhóm thu thập, bạn phải sử dụng phiên bản 2, hãy xem bảo mật các truy vấn nhóm thu thậ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 trong trường hợp nhiều biểu thức allow khớp với một yêu cầu, thì 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ả lượt đọc và ghi vào tập hợp cities sẽ được được phép vì quy tắc thứ hai luôn là true, mặc dù quy tắc đầu tiên quy tắc luôn là false.

Giới hạn đối với 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()getAfter() tối đa cho mỗi yêu cầu
  • 10 đối với yêu cầu một tài liệu và yêu cầu truy vấn.
  • 20 để đọc nhiều tài liệu, giao dịch và ghi hàng loạt. Giới hạn 10 trước đó cũng áp dụng cho mỗi hoạt động.

    Ví dụ: Giả sử bạn tạo một yêu cầu ghi theo lô bằng 3 thao tác ghi và quy tắc bảo mật của bạn dùng 2 tài liệu truy cập lệnh gọi để xác thực từng lần ghi. Trong trường hợp này, mỗi lượt 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 20 cuộc gọi truy cập.

Nếu vượt quá một trong hai giới hạn này, ứng dụng 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 không được tính vào giới hạn này.

Độ sâu tối đa của câu lệnh match lồng nhau 10
Độ dài đường dẫn tối đa trong các phân đoạn đường dẫn được cho phép trong một tập hợp các đoạn đường dẫn lồng nhau Câu lệnh match 100
Số biến thể chụ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ố tối đa của hàm 7
Số liên kết biến tối đa let trên mỗi hàm 10
Số lệnh gọi hàm đệ quy hoặc theo chu kỳ tối đa 0 &lpar;không được phép&rpar;
Số biểu thức tối đa được đánh giá trong mỗi yêu cầu 1.000
Kích thước tối đa của bộ quy tắc Quy tắc phải tuân theo hai giới hạn kích thước:
  • giới hạn 256 KB cho 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 cách sử dụng firebase deploy.
  • giới hạn 250 KB cho kích thước của bộ quy tắc được biên dịch khi Firebase xử lý nguồn và đặt nguồn đó hoạt động trên phụ trợ.

Cloud Storage

Cấu trúc cơ bản

Firebase Security Rules trong Cloud FirestoreCloud Storage sử dụng cấu trúc sau và cú pháp:

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 bạn cần hiểu rõ 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à mà bạn cho phép chạy. Các phương thức chuẩn là: get, list, create, updatedelete. Phương thức readwrite tiện lợi cho phép truy cập đọc và ghi trên đường dẫn lưu trữ hoặc cơ sở dữ liệu đượ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 nếu nó có kết quả là đúng.

Đường dẫn phù hợ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à cũng có thể lồng ghép các quy tắc. Nếu không có quy tắc so khớp nào cho phép phương thức yêu cầu hoặc điều kiện được đánh giá là false, yêu cầu bị từ chối.

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>;
  }
}

Kết quả 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 đơn lẻ, 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.

Bạn có thể tạo một 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 đoạn bằng cách thêm =** vào phương thức 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 trong kết quả của tất cả đánh giá quy tắc. Nghĩa là, nếu bất kỳ quy tắc nào mà tệp phù hợp có kết quả là true, kết quả là true

Trong các quy tắc trên, tệp "images/profilePhotos.png" có thể đọc được nếu condition hoặc other_condition cho kết quả là true, trong khi tệp "images/users/user:12345/profilePhoto.png" chỉ phải tuân theo kết quả của other_condition.

Biến ký tự đại diện có thể được tham chiếu từ trong tệp cung cấp match uỷ quyền tên hoặc đườ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 phân tầng và các quy tắc chỉ được đánh giá khi đường dẫn yêu cầu khớp với một đường dẫn có quy tắc được chỉ định.

Yêu cầu đánh giá

Các lượt 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 Đã gửi request 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 điểm yêu cầu được thực hiện đã nhận và giá trị resource mới nếu yêu cầu là một lượt ghi. Tiêu đề HTTP và trạng thái xác thực.

Đố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. Đối tượng này sẽ là giải thích thêm trong phần Xác thực của phần 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 ánh xạ<chuỗi, chuỗi> 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, bản đồ của Firebase Authentication xác nhận quyền sở hữu JWT. Nếu không, giá trị sẽ là null.
params ánh xạ<chuỗi, chuỗi> 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 tại.
resource ánh xạ<chuỗi, chuỗi> Giá trị tài nguyên mới chỉ hiển thị trên các yêu cầu write.
time dấu thời gian Dấu thời gian cho biết thời gian máy chủ đánh giá yêu cầu.

Đánh giá tài nguyên

Khi đánh giá 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à hiệu quả để thực hiện những việc như chỉ cho phép các tệp có loại nội dung được tải lên hoặc chỉ các tệp lớn hơn kích thước nhất định đã bị xoá.

Firebase Security Rules cho Cloud Storage cung cấp siêu dữ liệu tệp trong resource chứa các cặp khoá/giá trị của siêu dữ liệu được hiển thị trong một Đối tượng Cloud Storage. Bạn có thể kiểm tra các thuộc tính này trên read hoặc write yêu cầu để đả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 sẽ được 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 Google Cloud Storage tạo đối tượng của đối tượng này.
metageneration int Google Cloud Storage siêu dữ liệu đối tượng 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 thể hiện thời điểm một đối tượng được tạo.
updated dấu thời gian Dấu thời gian biểu thị 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 Bố cục nội dung liên kết với đối tượng này.
contentEncoding chuỗi Phương thức mã hoá nội dung liên kết với đối tượng này.
contentLanguage chuỗi Ngôn ngữ của 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 ánh xạ<chuỗi, chuỗi> 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 mã này, ngoại trừ generation, metageneration, etag, timeCreatedupdated.

Giới hạn đối với 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ượng tối đa firestore.exists()firestore.get() cuộc gọi 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 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 hình ảnh giải pháp lưu trữ:

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 một Tài liệu JSON.

Chúng 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. 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. read và quy tắc write cấp quyền đọc và ghi trên phạm vi rộng, trong khi quy tắc validate cấp đóng vai trò là phương thức xác minh thứ hai để cấp quyền truy cập dựa trên email đến hoặc mạng hiện có .
  • Điều kiện: Điều kiện cho phép một yêu cầu nếu yêu cầu đó được đánh giá là đúng.

Cách áp dụng quy tắc cho đường dẫn

Trong Realtime Database, Rules áp dụng nguyên tử, nghĩa là quy tắc ở nút mẹ cấp cao hơn ghi đè quy tắc tại các nút con và nút con chi tiết hơn 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 ở đường dẫn sâu hơn trong cấu trúc cơ sở dữ liệu của bạn nếu mà bạn đã cấp cho một trong các đường dẫn mẹ.

Hãy cân nhắc 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ó có hiệu lực tại đây, do đường dẫn con không thể thu hồi quyền truy cập.

Mặc dù có vẻ trực quan ngay lập tức, nhưng đây là một phần mạnh mẽ của ngôn ngữ của các quy tắc và cho phép triển khai các đặc quyền truy cập rất phức tạp mà không tốn nhiều công sức. Đ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, các quy tắc .validate không phân tầng. 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, do các quy tắc không áp dụng lại cho đường dẫn mẹ, nên tính năng đọc hoặc ghi không thực hiện được thao tác nếu không có quy tắc ở vị trí được yêu cầu hoặc tại một cấp độ gốc vị trí 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, việc đọc tại vị trí chính sẽ không thành công hoàn toàn. 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 chi tiết, có vẻ như chẳng hạn như 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
Lưu ý: Sản phẩm Firebase này không dùng được cho mục tiêu Đoạn video ngắn.
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
Lưu ý: Sản phẩm Firebase này không dùng được trên mục tiêu App Clip (Đoạn video ứng dụng).
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/ có tính 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ẽ tạo ra 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 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/. Tuy nhiên, 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 ta đã yêu cầu. Để tìm nạp rec1, chúng ta cần truy cập trực tiếp vào mã đó:

JavaScript
var db = firebase.database();
db.ref("records/rec1").once("value", function(snap) {
  // SUCCESS!
}, function(err) {
  // error callback is not called
});
Objective-C
Lưu ý: Sản phẩm Firebase này không dùng được cho mục tiêu Đoạn video ngắn.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
Swift
Lưu ý: Sản phẩm Firebase này không dùng được trên mục tiêu App Clip (Đoạn video ứng dụng).
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ợ $location để khớp với các phân đoạn đường dẫn. Sử dụng tiền tố $ ở trước đường dẫn của bạn để so 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 đường dẫn không đổi tên.

  {
    "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 }
      }
    }
  }