Cách thức 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ý việc 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 của Firebase loại bỏ lớp giữa (máy chủ) và cho phép bạn chỉ định các quyền dựa trên đường dẫn cho các máy 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 áp dụng các quy tắc 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 đá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 cho phép chạy. Các phương thức tiêu chuẩn là: get , list , create , updatedelete . Các phương thức readwrite thuận tiện 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ó sẵn. 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 định sử dụng truy vấn nhóm tuyển 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 trùng khớp phải trỏ đến tài liệu chứ không phải bộ sưu tập. 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 á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 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 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.

Hãy 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 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 biện pháp kiểm soát 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 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 đối với đường dẫn của câu lệnh match bên ngoài. Do đó, các bộ quy tắc sau 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 áp dụng các quy tắc 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 khớ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 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 cities và bộ sưu tập con.

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ó 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ỳ đâ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 .

Tuyên bố 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 có nhiều biểu thức allow khớp với một yêu cầu, quyền truy cập sẽ đượ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 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 một tài liệu 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 được áp dụng cho mỗi thao tác.

    Ví dụ: hãy tưởng tượng bạn tạo một yêu cầu ghi theo lô với 3 thao tác ghi và 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 đợt 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 từ chối cấp phép.

Một số cuộc gọi truy cập tài liệu có thể được lưu vào bộ nhớ đệm và các cuộc gọi được lưu vào bộ nhớ đệm 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, tính theo 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 chụp đườ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ố lượng đối số tối đa của hàm 7
Số lượng liên kết biến let tối đa cho mỗi hàm 10
Số lần 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 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 cách sử dụng firebase deploy .
  • giới hạn 250 KB đối với kích thước của bộ quy tắc được biên dịch xảy ra khi Firebase xử lý nguồn và kích hoạt nó ở phía sau.

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 cho phép chạy. Các phương thức tiêu chuẩn là: get , list , create , updatedelete . Các phương thức readwrite thuận tiện 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 các tệp trong Cloud Storage. 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 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 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>;
}

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 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, 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 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ả 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 khớp với giá trị 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ỉ tuân theo 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 xếp tầng 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á

Việc tải lên, tải xuống, thay đổi và xóa siêu dữ liệu đượ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 đượ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 bao gồm.

Đối tượng request cũng chứa ID duy nhất của người dùng và trọng tải Xác thực Firebase trong đối tượng request.auth , điều này 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 yêu cầu JWT xác thực Firebase. 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 Một 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 khi 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ủ thực hiện yêu cầu.

Đá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 lớn hơn một kích thước nhất định.

Quy tắc bảo mật Firebase cho Cloud Storage 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 hiển thị trong đối tượng Cloud Storage. 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 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 tồn tại ở đường dẫn yêu cầu, bạn còn có khả năng 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 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 dữ liệu hoặc thực thi các ràng buộc ứng dụng 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 nhóm chứa đối tượng này.
generation int Việc tạo đối tượng Google Cloud Storage của đối tượng này.
metageneration int Quá trình biến đổi đố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 đố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 liên kết với đối tượng này.
contentDisposition sợi dây Việc bố trí nội dung liên quan đến đố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ặ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 , timeCreatedupdated .

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 cuộc gọi firestore.exists()firestore.get() tối đa cho mỗi yêu cầu

2 cho các yêu cầu một tài liệu và yêu cầu truy vấn.

Vượt quá giới hạn này dẫn đến lỗi từ chối cấp phép.

Các cuộc 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 cuộc 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 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 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à các phương thức mà quy tắc sử dụng để cấp quyền truy cập. Quy tắc readwrite quyền truy cập đọc và ghi rộng rãi, trong khi quy tắc validate đóng vai trò 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 yêu cầu nếu nó đánh giá là đúng.

Cách áp dụng quy tắc 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 ở nút gốc cấp cao hơn sẽ ghi đè quy tắc ở nút con chi tiết hơn và 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 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 /bar/ được đọc từ bất cứ khi nào /foo/ chứa 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ù nó 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 việc 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 đáp ứng ở tất cả các cấp độ của hệ thống phân cấp để được phép ghi.

Ngoài ra, do 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 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í chính 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 ở vị trí gốc sẽ hoàn toàn không thành công. 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
Lưu ý: Sản phẩm Firebase này không có sẵn trên mục tiêu App Clip.
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
Lưu ý: Sản phẩm Firebase này không có sẵn trên mục tiêu App Clip.
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 mô phỏng bảo mật trong bảng điều khiển Firebase , 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 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 /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 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 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
Lưu ý: Sản phẩm Firebase này không có sẵn trên mục tiêu App Clip.
FIRDatabaseReference *ref = [[FIRDatabase database] reference];
[[ref child:@"records/rec1"] observeSingleEventOfType:FEventTypeValue withBlock:^(FIRDataSnapshot *snapshot) {
    // SUCCESS!
}];
Nhanh
Lưu ý: Sản phẩm Firebase này không có sẵn trên mục tiêu App Clip.
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ố $ 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 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 }
      }
    }
  }