限制Firebase数据库和存储的写入访问权限只针对特定组

3
我有一个React Redux Firebase应用程序,其中包含内容管理方面的功能(所有这些页面都以/admin/...开头)。我需要将Firebase数据库和Firebase存储写入访问权限限制在少量用户之内,并在未经身份验证(或已经过身份验证但没有管理员角色)的用户尝试进入时处理重定向。目前,任何人只要发现认证按钮位于/admin就可以使用Facebook或Google登录,然后获得访问权限。
根据我所了解的,似乎可以通过自定义令牌来实现此目的,但我不清楚将提供的代码片段放在哪里才能确保安全。我尝试手动在Firebase数据库中添加admin:true,然后像下面这样设置我的Firebase数据库规则:
{
  "rules": {
    ".read": "true",
    ".write": "auth != null && root.child('users').child(auth.uid).child('admin').val() == true"
  }
}

这种方法可以保护数据库的写入访问,但是我无法使用相同的管理员字段/令牌来控制Firebase存储,所以我不得不这样做:

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth!=null && request.auth.uid=="{my uid}";
      //request.auth.token.admin==true did not seem to work
    }
  }
}

我也无法在客户端上显示admin: true,因此目前没有重定向的方法。

请问有人能为我解决这个问题吗?


1
请查看此答案:https://dev59.com/lZbfa4cB1Zd3GeqPuXxr Firebase拥有管理员API,可以安全地定义自定义声明。 - bojeil
我想我只是不知道在我的应用程序中设置这些声明的正确位置。我使用create-react-app来搭建应用程序,似乎没有安全的地方导入firebase-admin。 - ZachO
我最终在 Firebase 云函数中尝试了这个方法 - 当用户创建时触发(虽然这不是一个适用的触发器,但我可以控制),并且正确地放置了声明,并像我需要的那样阻止了对数据库和存储的写入访问(通过编辑规则以检查管理员令牌)。您可以将此作为答案并接受它,但知道在哪里处理与 React 相关的服务器端逻辑可能会很好。 - ZachO
已在下面添加答案。 - bojeil
2个回答

4

限制访问少量(且稳定)用户的一种方法是使用他们的uid,并检查其是否包含在管理员用户uid数组中,如下所示:

function isAdminUser() {
   return request.auth.uid in [
        "UcqBSJOPDT........zzaeh1",
        "pQHSCZ1........hS2mfKmd2", 
        "MK8kif7.......eEqJzUl2n1", 
        "FrSm................XI82"
    ];
}

service firebase.storage {
  match /b/xxxxxxx.appspot.com/o {
    match /{allPaths=**} {
      allow write: .....;
      allow read: if request.auth != null && isAdminUser();
    }
  }
}

建议的isAdminUser()只是你在规则中手动维护的列表吗? - Wesley Barnes
@WesleyBarnes 是的,确实如此。这非常基础,这就是为什么我提到这种方法适用于“小型(且稳定)用户子集”的原因。它非常基础,但比使用Custom Claims更简单,正如bojeil在他的答案中建议的那样,如果您的管理员用户列表很长或经常更改,则绝对是正确的方法。 - Renaud Tarnec

2
Firebase 支持通过 ID token 上的自定义用户声明为任何用户支持基于角色的访问权限,参考链接: https://firebase.google.com/docs/auth/admin/custom-claims 您可以定义管理员访问规则:
{
  "rules": {
    "adminContent": {
      ".read": "auth.token.admin === true",
      ".write": "auth.token.admin === true",
    }
  }
}

使用 Admin SDK 在服务器上设置用户角色。您可以使用自己的服务器,或者通过云函数中的 onCreate 事件进行设置(只要您能够从那里确定谁是管理员,谁不是),等等:

// Set admin privilege on the user corresponding to uid.
admin.auth().setCustomUserClaims(uid, {admin: true}).then(() => {
  // The new custom claims will propagate to the user's ID token the
  // next time a new one is issued.
});

这将传播到相应用户的ID令牌声明。
要从客户端的令牌中解析它,请检查:https://firebase.google.com/docs/auth/admin/custom-claims#access_custom_claims_on_the_client 你基本上需要对令牌的有效载荷进行base64解码。但是,如果你正在运行自己的服务器端代码,请始终依赖Firebase规则或ID令牌验证进行服务器端验证。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接