【问题标题】:Firebase Storage security rule error- User does not have permissionFirebase 存储安全规则错误 - 用户没有权限
【发布时间】:2016-11-23 07:11:42
【问题描述】:

我正在使用 自定义令牌 对 Firebase 进行身份验证。我想限制只有当前用户有权写入和删除图像并授予所有人读取权限。

以下代码是我与存储相关的快速代码的一部分

let filePath = REF_STORAGE.child("/"+(FIRAuth.auth()?.currentUser?.uid)!+"/profilepic.jpeg")
let metaData = FIRStorageMetadata()
metaData.contentType = "image/jpeg"

而我目前的firebase存储规则如下图

service firebase.storage {
  match /b/test-123456789.appspot.com/o {
    match /{uid}/{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth.uid == uid;
    }
  }
}

当我尝试上传图片时出现以下错误

用户无权访问 gs://test-123456789.appspot.com/MYAUTHUID/profilepic.jpeg。

但如果我将存储规则更改为以下存储规则,我可以上传图片,并且 profilepic 存储在 /gs://test-123456789.appspot.com/123456789/profilepic.jpeg 下

service firebase.storage {
  match /b/test-123456789.appspot.com/o {
    match /{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth != null;
    }
  }
}

请告诉我如何解决此问题。

【问题讨论】:

  • 你确定你没有过度简化你的例子吗?因为您提供的规则与 firebase.google.com/docs/storage/security/… 基本相同,因此应该可以工作。
  • @Dreamcooled。从早上开始就一直在这个问题上我还没有想出解决方案
  • 你忘了回答我的问题
  • @Dreamcooled。是的,我很确定:)

标签: firebase firebase-security firebase-storage


【解决方案1】:

您的{uid} 是否包含任何特殊字符? (例如“+”号)

注意Firebase Support 回复我说这个问题正在调查中,在我 3 天前发送给他们的错误报告之后:我发现调用 {userid} 对我不起作用Firebase 存储规则(如果它包含“+”号)。

我使用 E.164 格式的电话号码(例如:"+97234567899")。 我尝试了几次运行测试,它们清楚地表明从 {uid} 返回的值存在问题:

  1. request.auth != null; - 工作
  2. request.auth.uid != null; - 工作
  3. request.auth.uid == "+97234567899"; - 工作
  4. request.auth.uid == uid; - 没用

但是,我找到了绕过此问题的方法。这是我想出的:


解决方案

resource.name.split('/')[position]

由于 {uid} 代表文件夹名称,您可以通过使用 resource.name 操作文件的完整路径字符串,将其以 ('/') 分割,然后选择相关层次结构来提取其值。

例如:如果这是您的路径:/Images/Profiles/{uid}/profile.jpg,则像这样提取 uid:resource.name.split('/')[2]

在您的代码示例中,我会这样做:

service firebase.storage {
  match /b/test-123456789.appspot.com/o {
    match /{uid}/{allPaths=**} {
      allow read: if request.auth != null;
      allow write: if request.auth.uid == resource.name.split('/')[0];
    }
  }
}

编辑(2017 年 7 月 28 日)

Firebase 支持已在一个月前回复了我的报告,该问题已被确定并正在处理中。

但是,与此同时,如果您希望通过电话号码进行身份验证(就像我一样) - 我们不应该再使用自定义令牌,因为 Firebase 现在支持这种身份验证。

【讨论】:

    【解决方案2】:

    对于仍然遇到此问题的任何人:将您的 Firebase 安全规则更新为以下对我来说是诀窍。

    service firebase.storage {
      match /b/{bucket}/o {
        match /{allPaths=**} {
          allow read, write: if request.auth.uid != null;
        }
      }
    }  
    

    【讨论】: