基于 Firestore 数据的 Firebase 云存储规则变通
Firebase Cloud Storage rules based on Firestore Data work around
在我的 firebase 应用程序中我有
- 用户列表(所有用户均通过 Firebase 身份验证注册)
- 每个用户的关注者列表
- 每个用户都添加了个人资料照片,照片的文件名是唯一的,保存在名为“photoName”的 firestore 文档中
- 仅允许用户的关注者阅读“photoName”文档(如 firestore 规则中所指定)
我只希望关注者可以看到用户的头像,我在云存储中添加了如下规则:
match /profilePhotos/{profilePhotoFile_id} {
allow read: if request.auth.uid != null
}
云存储规则是在文件级别设置的,所以我假设只有登录并且也是关注者的用户才能阅读其他用户的个人资料照片是否准确?除非他们以某种方式神奇地猜出照片的唯一名称。
Is it accurate for me to assume that only the users who are logged in
and are also a follower will be able to read the profile photo of
another user?
不,因为客户端 SDK 可以列出 Cloud Storage 存储桶中的所有文件,因为 explained in the doc 并且您的 Cloud Storage 安全规则允许任何经过身份验证的用户读取个人资料照片文件。
另请注意,您在编写云存储安全规则时无法读取 Firestore 文档。
一种可能的方法是使用 Cloud Function 生成已签名的 URL 并存储在 Firestore 文档中 AND 以禁止对个人资料照片文件。由于 Cloud Functions 使用 Admin SDK,它们可以绕过安全规则。
每次将文件添加到 Cloud Storage 并将其保存在 Firestore 文档中时,以下 Cloud Function 代码将生成一个已签名的 URL。有了这个签名 URL 任何人都可以阅读个人资料照片文件。
您可以通过以下方式使其适应您的情况:
- 如有必要,只处理个人资料照片(检查文件名是否包含
profilePhotos
)
- 在正确的 Firestore 文档中保存 URL:我猜文件名允许链接回用户文档。此外,您可能必须将
add()
更改为 update()
。
exports.generateFileURL = functions.storage.object().onFinalize(async object => {
try {
const bucket = admin.storage().bucket(object.bucket);
const file = bucket.file(object.name);
const signedURLconfig = { action: 'read', expires: '08-12-2025' };
const signedURLArray = await file.getSignedUrl(signedURLconfig);
const url = signedURLArray[0];
await admin.firestore().collection('...').add({ signedURL: url })
return null;
} catch (error) {
console.log(error);
return null;
}
});
另外两个注意事项:
- 您可以使用 Custom Claims in Cloud Storage Security Rules, but it is not really recommended to use them for your case, see here.
- 您也可以在云存储安全规则中使用文件元数据,但同样不适合您的情况(您不会在每次新关注者注册时在文件元数据中添加关注者 ID...)
在我的 firebase 应用程序中我有
- 用户列表(所有用户均通过 Firebase 身份验证注册)
- 每个用户的关注者列表
- 每个用户都添加了个人资料照片,照片的文件名是唯一的,保存在名为“photoName”的 firestore 文档中
- 仅允许用户的关注者阅读“photoName”文档(如 firestore 规则中所指定)
我只希望关注者可以看到用户的头像,我在云存储中添加了如下规则:
match /profilePhotos/{profilePhotoFile_id} {
allow read: if request.auth.uid != null
}
云存储规则是在文件级别设置的,所以我假设只有登录并且也是关注者的用户才能阅读其他用户的个人资料照片是否准确?除非他们以某种方式神奇地猜出照片的唯一名称。
Is it accurate for me to assume that only the users who are logged in and are also a follower will be able to read the profile photo of another user?
不,因为客户端 SDK 可以列出 Cloud Storage 存储桶中的所有文件,因为 explained in the doc 并且您的 Cloud Storage 安全规则允许任何经过身份验证的用户读取个人资料照片文件。
另请注意,您在编写云存储安全规则时无法读取 Firestore 文档。
一种可能的方法是使用 Cloud Function 生成已签名的 URL 并存储在 Firestore 文档中 AND 以禁止对个人资料照片文件。由于 Cloud Functions 使用 Admin SDK,它们可以绕过安全规则。
每次将文件添加到 Cloud Storage 并将其保存在 Firestore 文档中时,以下 Cloud Function 代码将生成一个已签名的 URL。有了这个签名 URL 任何人都可以阅读个人资料照片文件。
您可以通过以下方式使其适应您的情况:
- 如有必要,只处理个人资料照片(检查文件名是否包含
profilePhotos
) - 在正确的 Firestore 文档中保存 URL:我猜文件名允许链接回用户文档。此外,您可能必须将
add()
更改为update()
。
exports.generateFileURL = functions.storage.object().onFinalize(async object => {
try {
const bucket = admin.storage().bucket(object.bucket);
const file = bucket.file(object.name);
const signedURLconfig = { action: 'read', expires: '08-12-2025' };
const signedURLArray = await file.getSignedUrl(signedURLconfig);
const url = signedURLArray[0];
await admin.firestore().collection('...').add({ signedURL: url })
return null;
} catch (error) {
console.log(error);
return null;
}
});
另外两个注意事项:
- 您可以使用 Custom Claims in Cloud Storage Security Rules, but it is not really recommended to use them for your case, see here.
- 您也可以在云存储安全规则中使用文件元数据,但同样不适合您的情况(您不会在每次新关注者注册时在文件元数据中添加关注者 ID...)