Catch up on everthing we announced at this year's Firebase Summit. Learn more

Viết điều kiện cho Quy tắc bảo mật Cloud Firestore

Hướng dẫn này được xây dựng trên các quy tắc bảo mật cơ cấu hướng dẫn để hiển thị như thế nào để thêm điều kiện để Security Rules FireStore Cloud của bạn. Nếu bạn không quen thuộc với những điều cơ bản của Cloud Security Rules FireStore, xem bắt đầu nhận được hướng dẫn.

Khối xây dựng chính của Quy tắc bảo mật Cloud Firestore là điều kiện. Điều kiện là một biểu thức boolean xác định xem một hoạt động cụ thể nên được phép hay bị từ chối. Sử dụng các quy tắc bảo mật để viết các điều kiện kiểm tra xác thực người dùng, xác thực dữ liệu đến hoặc thậm chí truy cập các phần khác của cơ sở dữ liệu của bạn.

Xác thực

Một trong những mẫu quy tắc bảo mật phổ biến nhất là kiểm soát quyền truy cập dựa trên trạng thái xác thực của người dùng. Ví dụ: ứng dụng của bạn có thể muốn chỉ cho phép người dùng đã đăng nhập ghi dữ liệu:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

Một mô hình phổ biến khác là đảm bảo người dùng chỉ có thể đọc và ghi dữ liệu của riêng họ:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

Nếu ứng dụng của bạn sử dụng căn cứ hỏa lực Authentication hoặc đám mây danh tính nền tảng Google , các request.auth biến chứa các thông tin xác thực cho các khách hàng yêu cầu dữ liệu. Để biết thêm thông tin về request.auth , xem tài liệu tham khảo .

Xác nhận dữ liệu

Nhiều ứng dụng lưu trữ thông tin kiểm soát truy cập dưới dạng các trường trên tài liệu trong cơ sở dữ liệu. Quy tắc bảo mật Cloud Firestore có thể tự động cho phép hoặc từ chối quyền truy cập dựa trên dữ liệu tài liệu:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Các resource biến liên quan đến tài liệu được yêu cầu, và resource.data là một bản đồ của tất cả các lĩnh vực và các giá trị được lưu trữ trong tài liệu. Để biết thêm thông tin về resource biến, hãy xem tài liệu tham khảo .

Khi ghi dữ liệu, bạn có thể muốn so sánh dữ liệu đến với dữ liệu hiện có. Trong trường hợp này, nếu ruleset của bạn cho phép ghi chờ giải quyết, các request.resource biến chứa các trạng thái tương lai của tài liệu. Đối với update hoạt động mà chỉ sửa đổi một tập hợp con của các lĩnh vực tài liệu, request.resource biến sẽ chứa trạng thái tài liệu chờ xử lý sau phẫu thuật. Bạn có thể kiểm tra giá trị trường trong request.resource để ngăn chặn cập nhật dữ liệu không mong muốn hoặc không phù hợp:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

Truy cập các tài liệu khác

Sử dụng get()exists() chức năng, quy tắc bảo mật của bạn có thể đánh giá yêu cầu đến chống lại các tài liệu khác trong cơ sở dữ liệu. Các get()exists() chức năng cả mong đợi đường dẫn tài liệu quy định đầy đủ. Khi sử dụng biến con đường xây dựng cho get()exists() , bạn cần phải thoát khỏi một cách rõ ràng các biến bằng cách sử dụng $(variable) cú pháp.

Trong ví dụ dưới đây, các database biến được chụp bởi các trận đấu tuyên bố match /databases/{database}/documents và sử dụng để tạo đường dẫn:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid))

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true
    }
  }
}

Đối với lần ghi, bạn có thể sử dụng getAfter() chức năng để truy cập trạng thái của một tài liệu sau một giao dịch hoặc lô viết Hoàn thành nhưng trước khi giao dịch hoặc hàng loạt cam kết. Giống như get() , các getAfter() chức năng phải mất một con đường tài liệu quy định đầy đủ. Bạn có thể sử dụng getAfter() để xác định bộ ghi rằng phải diễn ra với nhau như một giao dịch hoặc hàng loạt.

Truy cập giới hạn cuộc gọi

Có một giới hạn đối với các cuộc gọi truy cập tài liệu cho mỗi đánh giá bộ quy tắc:

  • 10 cho các yêu cầu một tài liệu và các 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 trước đó là 10 cũng được áp dụng cho mỗi hoạt động.

    Ví dụ: hãy tưởng tượng bạn tạo một yêu cầu ghi hàng loạt với 3 thao tác ghi và các 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 của nó và yêu cầu ghi theo đợt sử dụng 6 trong số 20 lệnh gọi truy cập của nó.

Vượt quá một trong hai giới hạn dẫn đến lỗi bị 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 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.

Đối với một lời giải thích chi tiết về cách thức các giới hạn ảnh hưởng đến giao dịch và batched viết, hãy xem hướng dẫn để đảm bảo hoạt động nguyên tử .

Truy cập cuộc gọi và giá cả

Việc sử dụng các hàm này sẽ thực hiện thao tác đọc trong cơ sở dữ liệu của bạn, có nghĩa là bạn sẽ bị tính phí cho việc đọc tài liệu ngay cả khi các quy tắc của bạn từ chối yêu cầu. Xem đám mây FireStore giá để biết thông tin thanh toán cụ thể hơn.

Các chức năng tùy chỉnh

Khi các quy tắc bảo mật của bạn trở nên phức tạp hơn, bạn có thể muốn bao bọc các nhóm điều kiện trong các hàm mà bạn có thể sử dụng lại trên bộ quy tắc của mình. Các quy tắc bảo mật hỗ trợ các chức năng tùy chỉnh. Cú pháp cho các hàm tùy chỉnh hơi giống JavaScript, nhưng các hàm quy tắc bảo mật được viết bằng ngôn ngữ dành riêng cho miền có một số hạn chế quan trọng:

  • Chức năng có thể chứa chỉ có một return tuyên bố. Chúng không thể chứa bất kỳ logic bổ sung nào. Ví dụ, chúng không thể thực hiện các vòng lặp hoặc gọi các dịch vụ bên ngoài.
  • Các hàm có thể tự động truy cập các hàm và biến từ phạm vi mà chúng được xác định. Ví dụ, một chức năng được xác định trong phạm vi service cloud.firestore phạm vi có quyền truy cập vào các resource khác nhau và tích hợp các chức năng như get()exists() .
  • Các hàm có thể gọi các hàm khác nhưng không thể đệ quy. Tổng độ sâu ngăn xếp cuộc gọi được giới hạn ở 10.
  • Trong quy tắc phiên bản v2 , chức năng có thể định nghĩa biến bằng cách sử dụng let từ khóa. Các hàm có thể có tối đa 10 liên kết let, nhưng phải kết thúc bằng câu lệnh trả về.

Một chức năng được định nghĩa với function khóa và mất không hay nhiều đối số. Ví dụ: bạn có thể muốn kết hợp hai loại điều kiện được sử dụng trong các ví dụ trên thành một hàm duy nhất:

service cloud.firestore {
  match /databases/{database}/documents {
    // True if the user is signed in or the requested data is 'public'
    function signedInOrPublic() {
      return request.auth.uid != null || resource.data.visibility == 'public';
    }

    match /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Việc sử dụng các hàm trong các quy tắc bảo mật của bạn giúp chúng dễ bảo trì hơn khi mức độ phức tạp của các quy tắc của bạn ngày càng tăng.

Quy tắc không phải là bộ lọc

Sau khi bạn bảo mật dữ liệu của mình và bắt đầu viết truy vấn, hãy nhớ rằng các quy tắc bảo mật không phải là bộ lọc. Bạn không thể viết truy vấn cho tất cả các tài liệu trong một bộ sưu tập và mong đợi Cloud Firestore chỉ trả lại các tài liệu mà ứng dụng khách hiện tại có quyền truy cập.

Ví dụ: lấy quy tắc bảo mật sau:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Bị từ chối: Quy tắc này từ chối các truy vấn sau đây vì tập kết quả có thể bao gồm các tài liệu mà visibility không phải là public :

Web
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

Cho phép: Quy tắc này cho phép các truy vấn sau đây vì where("visibility", "==", "public") đảm bảo khoản rằng kết quả thiết lập thỏa mãn điều kiện của quy tắc:

Web
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

Các quy tắc bảo mật của Cloud Firestore đánh giá từng truy vấn dựa trên kết quả tiềm năng của nó và không thực hiện được yêu cầu nếu nó có thể trả về tài liệu mà khách hàng không có quyền đọc. Các truy vấn phải tuân theo các ràng buộc do các quy tắc bảo mật của bạn đặt ra. Để biết thêm về quy tắc bảo mật và truy vấn, xem một cách an toàn truy vấn dữ liệu .

Bước tiếp theo