Google cam kết thúc đẩy công bằng chủng tộc cho Cộng đồng người da đen. Xem cách thực hiện.
Trang này được dịch bởi Cloud Translation API.
Switch to English

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

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

Khối xây dựng chính của Quy tắc bảo mật Cloud Firestore là điều kiện. Một đ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 cho phép hay 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 trong 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 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ể chỉ muốn 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 Xác thực Firebase, biến request.auth chứa thông tin xác thực cho ứng dụng khách 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 của Cloud Firestore có thể tự động cho phép hoặc từ chối 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';
    }
  }
}
 

Biến resource đề cập đến tài liệu được yêu cầu và resource.data là bản đồ của tất cả các trường và giá trị được lưu trữ trong tài liệu. Để biết thêm thông tin về biến resource , 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 bộ quy tắc của bạn cho phép ghi chờ xử lý, biến request.resource chứa trạng thái tương lai của tài liệu. Đối với các hoạt động update chỉ sửa đổi một tập hợp con của các trường tài liệu, biến request.resource sẽ chứa trạng thái tài liệu đang chờ xử lý sau thao tác. Bạn có thể kiểm tra các giá trị trường trong request.resource để ngăn cập nhật dữ liệu không mong muốn hoặc không nhất quán:

 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 các hàm get()exists() , các quy tắc bảo mật của bạn có thể đánh giá các yêu cầu đến đối với các tài liệu khác trong cơ sở dữ liệu. Cả hai hàm get()exists() đều mong đợi các đường dẫn tài liệu được chỉ định đầy đủ. Khi sử dụng các biến để xây dựng các đường dẫn cho get()exists() , bạn cần thoát các biến một cách rõ ràng bằng cú pháp $(variable) .

Trong ví dụ dưới đây, biến database được bắt bởi câu lệnh match /databases/{database}/documents và được 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
    }
  }
}
 

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

Giới hạn truy cập cuộc gọi

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

  • 10 cho các yêu cầu tài liệu đơn và yêu cầu truy vấn.
  • 20 cho nhiều tài liệu đọc, giao dịch và viết theo đợt. Giới hạn 10 trước đó cũng áp dụng cho từng thao tác.

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

Vượt quá giới hạn 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 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 các giới hạn.

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

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

Sử dụng các hàm này sẽ thực thi thao tác đọc trong cơ sở dữ liệu của bạn, điều đó có nghĩa là bạn sẽ được lập hóa đơn để đọc tài liệu ngay cả khi quy tắc của bạn từ chối yêu cầu. Xem Giá cả của Firestore để biết thêm thông tin thanh toán cụ thể.

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 bọc các bộ điều kiện trong các chức năng mà bạn có thể sử dụng lại trên quy tắc của mình. 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 với 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 tên miền có một số hạn chế quan trọng:

  • Các hàm chỉ có thể chứa một câu lệnh return . Chúng không thể chứa bất kỳ logic bổ sung. Ví dụ, họ không thể thực thi 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 hàm được xác định trong phạm vi service cloud.firestore có quyền truy cập vào biến resource và các hàm dựng sẵn như get()exists() .
  • Các chức năng có thể gọi các chức năng khác nhưng có thể không tái diễn. Tổng độ sâu ngăn xếp cuộc gọi được giới hạn là 10.
  • Trong quy tắc phiên bản v2 , các hàm có thể xác định các biến bằng cách sử dụng từ khóa let . Các hàm có thể có tối đa 10 cho phép liên kết, nhưng phải kết thúc bằng câu lệnh return.

Một hàm được định nghĩa với từ khóa function và không có hoặc 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();
    }
  }
}
 

Sử dụng các chức năng trong các quy tắc bảo mật của bạn làm cho chúng dễ bảo trì hơn khi sự phức tạp của các quy tắc của bạn tăng lên.

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

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 bộ sưu tập và mong muốn Cloud Firestore chỉ trả lại các tài liệu mà khách hàng 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 truy vấn sau vì tập kết quả có thể bao gồm các tài liệu không visibility public :

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

Được phép : Quy tắc này cho phép truy vấn sau vì mệnh đề where("visibility", "==", "public") đảm bảo rằng tập kết quả 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 so với kết quả tiềm năng của nó và không yêu cầu nếu nó có thể trả về một 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 được đặt bởi các quy tắc bảo mật của bạn. Để biết thêm về các quy tắc và truy vấn bảo mật, hãy xem dữ liệu truy vấn an toàn .

Bước tiếp theo