Hướng dẫn này dựa trên hướng dẫn tìm hiểu cú pháp cốt lõi của ngôn ngữ Firebase Security Rules để cho biết cách thêm điều kiện vào Firebase Security Rules cho Cloud Storage.
Thành phần cơ bản của Cloud Storage Security Rules là điều kiện. Điều kiện là một biểu thức boolean xác định xem một thao tác cụ thể có được phép hay không. Đối với các quy tắc cơ bản, việc sử dụng các ký tự cố định true
và false
làm điều kiện hoạt động rất hiệu quả. Nhưng Firebase Security Rules cho ngôn ngữ Cloud Storage cung cấp cho bạn những cách viết các điều kiện phức tạp hơn có thể:
- Kiểm tra hoạt động xác thực người dùng
- Xác thực dữ liệu đến
Xác thực
Firebase Security Rules cho Cloud Storage tích hợp với Firebase Authentication để cung cấp tính năng xác thực mạnh mẽ dựa trên người dùng cho Cloud Storage. Điều này cho phép kiểm soát quyền truy cập chi tiết dựa trên các xác nhận quyền sở hữu của mã thông báo Firebase Authentication.
Khi người dùng đã xác thực thực hiện một yêu cầu đối với Cloud Storage, biến request.auth
sẽ được điền bằng uid
(request.auth.uid
) của người dùng cũng như các thông tin xác nhận của JWT Firebase Authentication (request.auth.token
).
Ngoài ra, khi sử dụng tính năng xác thực tuỳ chỉnh, các thông tin bổ sung sẽ xuất hiện trong trường request.auth.token
.
Khi người dùng chưa xác thực thực hiện một yêu cầu, biến request.auth
sẽ là null
.
Dựa vào dữ liệu này, có một số cách phổ biến để dùng hoạt động xác thực nhằm bảo mật các tệp:
- Công khai: bỏ qua
request.auth
- Riêng tư đã xác thực: kiểm tra để đảm bảo
request.auth
không phải lànull
- User private: check that
request.auth.uid
equals a pathuid
- Nhóm riêng tư: kiểm tra các khai báo của mã thông báo tuỳ chỉnh để khớp với một khai báo đã chọn hoặc đọc siêu dữ liệu của tệp để xem có trường siêu dữ liệu nào hay không
Công khai
Mọi quy tắc không xem xét bối cảnh request.auth
đều có thể được coi là quy tắc public
, vì quy tắc đó không xem xét bối cảnh xác thực của người dùng.
Những quy tắc này có thể hữu ích trong việc hiển thị dữ liệu công khai, chẳng hạn như tài sản trò chơi, tệp âm thanh hoặc nội dung tĩnh khác.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
Riêng tư và đã xác thực
Trong một số trường hợp, bạn có thể muốn tất cả người dùng đã xác thực của ứng dụng đều có thể xem dữ liệu, nhưng người dùng chưa xác thực thì không. Vì biến request.auth
là null
đối với tất cả người dùng chưa được xác thực, nên bạn chỉ cần kiểm tra xem biến request.auth
có tồn tại hay không để yêu cầu xác thực:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Người dùng ở chế độ riêng tư
Trường hợp sử dụng phổ biến nhất cho request.auth
là cung cấp cho từng người dùng các quyền chi tiết đối với tệp của họ: từ việc tải ảnh hồ sơ lên đến đọc các tài liệu riêng tư.
Vì các tệp trong Cloud Storage có "đường dẫn" đầy đủ đến tệp, nên tất cả những gì cần thiết để người dùng kiểm soát một tệp là một đoạn thông tin nhận dạng người dùng duy nhất trong tiền tố tên tệp (chẳng hạn như uid
của người dùng) có thể được kiểm tra khi quy tắc được đánh giá:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
Nhóm riêng tư
Một trường hợp sử dụng phổ biến không kém khác là cho phép nhóm có quyền đối với một đối tượng, chẳng hạn như cho phép một số thành viên trong nhóm cộng tác trên một tài liệu dùng chung. Có một số cách để thực hiện việc này:
- Phát hành một Firebase Authentication mã thông báo tuỳ chỉnh chứa thông tin bổ sung về một thành viên nhóm (chẳng hạn như mã nhận dạng nhóm)
- Thêm thông tin về nhóm (chẳng hạn như mã nhóm hoặc danh sách
uid
được uỷ quyền) vào siêu dữ liệu tệp
Sau khi được lưu trữ trong siêu dữ liệu của mã thông báo hoặc tệp, dữ liệu này có thể được tham chiếu từ bên trong một quy tắc:
// Allow reads if the group ID in your token matches the file metadata's `owner` property // Allow writes if the group ID is in the user's custom token match /files/{groupId}/{fileName} { allow read: if resource.metadata.owner == request.auth.token.groupId; allow write: if request.auth.token.groupId == groupId; }
Yêu cầu đánh giá
Các thao tác 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. Ngoài 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
như mô tả ở trên, biến request
chứa đường dẫn tệp nơi yêu cầu đang được thực hiện, thời gian nhận được yêu cầu và giá trị resource
mới nếu yêu cầu là một thao tác ghi.
Đố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 Bảo mật dựa trên người dùng 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 đồ gồm các xác nhận quyền sở hữu Firebase Authentication JWT. 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 | Một 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ỉ có trong cá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ủ mà yêu cầu được đánh giá. |
Đá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 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ẽ, chẳng hạn 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 yêu cầu read
hoặc write
để đảm bảo tính toàn vẹn của 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à 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 của 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 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 vùng chứa mà đối tượng này nằm trong. |
generation |
int | Google Cloud Storagetạo đối tượng của đối tượng này. |
metageneration |
int | Google Cloud Storagemetageneration 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 tạo một đối tượng. |
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 | Một hàm băm MD5 của đối tượng. |
crc32c |
chuỗi | Một hàm băm crc32c của đối tượng. |
etag |
chuỗi | Etag được liên kết với đối tượng này. |
contentDisposition |
chuỗi | Trạng thái nội dung được liên kết với đối tượng này. |
contentEncoding |
chuỗi | Phương thức 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 được liên kết với đối tượng này. |
contentType |
chuỗi | Loại nội dung được 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 phần tử này, ngoại trừ generation
, metageneration
, etag
, timeCreated
và updated
.
Nâng cao bằng Cloud Firestore
Bạn có thể truy cập vào các tài liệu trong Cloud Firestore để đánh giá các tiêu chí uỷ quyền khác.
Khi sử dụng các hàm firestore.get()
và firestore.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 dựa trên các tài liệu trong Cloud Firestore.
Cả hai hàm firestore.get()
và firestore.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 để tạo đường dẫn cho firestore.get()
và firestore.exists()
, bạn cần phải thoát các biến một cách rõ ràng bằng cách sử dụng cú pháp $(variable)
.
Trong ví dụ bên dưới, chúng ta thấy một quy tắc hạn chế quyền đọc đối với các tệp cho những người dùng là thành viên của một số câu lạc bộ cụ thể.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
Sau khi tạo và lưu Cloud Storage Security Rules đầu tiên sử dụng các hàm Cloud Firestore này, bạn sẽ được nhắc trong bảng điều khiển Firebase hoặc CLI Firebase để bật quyền kết nối hai sản phẩm.
Bạn có thể tắt tính năng này bằng cách xoá một vai trò IAM, như mô tả trong phần Quản lý và triển khai Firebase Security Rules.
Xác thực dữ liệu
Firebase Security Rules cho Cloud Storage cũng có thể được dùng để xác thực dữ liệu, bao gồm cả việc xác thực tên và đường dẫn tệp cũng như các thuộc tính siêu dữ liệu của tệp, chẳng hạn như contentType
và size
.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
Hàm tuỳ chỉnh
Khi Firebase Security Rules trở nên phức tạp hơn, bạn có thể muốn gói các nhóm điều kiện trong các hàm mà bạn có thể dùng lại trong bộ quy tắc. Quy tắc bảo mật hỗ trợ các hàm tuỳ chỉnh. Cú pháp cho các hàm tuỳ chỉnh hơi giống với JavaScript, nhưng các hàm Firebase Security Rules được viết bằng một ngôn ngữ dành riêng cho 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
duy nhất. Chúng không thể chứa bất kỳ logic bổ sung nào. Ví dụ: chúng 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 vào 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 firebase.storage
có quyền truy cập vào biếnresource
và chỉ đối với Cloud Firestore, các hàm tích hợp sẵn nhưget()
vàexists()
. - Các hàm có thể gọi các hàm khác nhưng không được đệ quy. Tổng số ngăn xếp lệnh gọi bị giới hạn ở mức 10.
- Trong phiên bản
rules2
, các hàm có thể xác định biến bằng từ khoálet
. Hàm có thể có bao nhiêu liên kết let tuỳ ý, nhưng phải kết thúc bằng một câu lệnh return.
Hàm được xác định bằng từ khoá function
và nhận 0 hoặc nhiều đối số. Ví dụ: bạn có thể muốn kết hợp 2 loại điều kiện được dùng trong các ví dụ ở trên thành một hàm duy nhất:
service firebase.storage {
match /b/{bucket}/o {
// 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 /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
Việc sử dụng các hàm trong Firebase Security Rules giúp bạn dễ dàng duy trì hơn khi độ phức tạp của các quy tắc tăng lên.
Các bước tiếp theo
Sau khi thảo luận về các điều kiện này, bạn sẽ hiểu rõ hơn về Quy tắc và sẵn sàng:
Tìm hiểu cách xử lý các trường hợp sử dụng cốt lõi và tìm hiểu quy trình phát triển, kiểm thử và triển khai Quy tắc:
- Viết các quy tắc giải quyết các trường hợp phổ biến.
- Củng cố kiến thức bằng cách xem xét những tình huống mà bạn phải phát hiện và tránh các Quy tắc không an toàn.
- Kiểm thử các quy tắc bằng trình mô phỏng Cloud Storage và thư viện kiểm thử Quy tắc bảo mật chuyên dụng.
- Xem xét các phương thức có sẵn để triển khai Rules.