我的Firebase网络应用需要管理员访问权限,即用户界面应仅向管理员显示一些内容(管理员'部分)。我想出了下面的方法来授权UI只显示有效管理员的管理部分。我的问题是,好还是坏?这是一种合理的授权方式吗? ......有很多方法可以做到这一点。这种特殊方式要求我在安全规则中配置管理员(vs在db / firestore中的节点/树中)
我的想法是,如果.get()
由于未经授权的访问而失败,我告诉我的应用逻辑用户不是管理员,如果.get()
成功我的逻辑显示' admin&# 39;部分。当然,'部分'只是数据库填充的HTML骨架/空元素,所以即使最终用户攻击JS /逻辑,也不会有真正的数据 - 只有空的管理部分'框架。
function isAdmin(){
return new Promise(function(resolve, reject){
var docRef = firebase.firestore().collection("authorize").doc("admin");
docRef.get().then(function(result) {
if (result) {
resolve (true);
}
}).catch(function(error) {
resolve (false);
});
});
}
firestore规则指定' admins'由UID。
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth.uid == "9mB3UxxxxxxxxxxxxxxxxxxCk1";
}
}
}
答案 0 :(得分:2)
您将每个用户的角色存储在数据库中,然后在客户端中查找以更新其UI。这曾经是很长时间在实时数据库上的惯用方式,它仍然适用于Firestore。
我唯一要改变的是让规则也从/authorize/admin
读取,而不是在其中硬编码UID。这样,您只在一个地方拥有UID,而不是在规则和文档中都有它。
但您可能还想考虑另一种方法:为您的管理员用户设置自定义声明,然后您可以同时阅读server-side security rules(以强制授权访问)和front-end(至优化用户界面。)
致set a custom claim you use the Firebase Admin SDK。您可以在云功能中的自定义服务器上执行此操作,但在您的方案中,从开发计算机运行它可能更简单。
答案 1 :(得分:1)
详细操作方法:Firebase具有此功能的自定义声明,详见其Control Access with Custom Claims and Security Rules。基本上,您站起来一个单独的节点服务器,安装Firebase AdminSDK:
npm install firebase-admin --save
从Firebase控制台的“服务帐户”标签中Generate/Download a Private Key并将其放在节点服务器上。然后,只需创建一个裸骨节点应用程序,为您希望的每个UID(用户)分配自定义声明。像下面这样的东西对我有用:
var admin = require('firebase-admin');
var serviceAccount = require("./the-key-you-generated-and-downloaded.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://xxxxxxxxxxxxxxxxxxxx.firebaseio.com"
});
admin.auth().setCustomUserClaims("whatever-uid-you-want-to-assign-claim-to", {admin: true}).then(() => {
console.log("Custom Claim Added to UID. You can stop this app now.");
});
就是这样。您现在可以通过退出应用程序(如果您之前已登录)验证是否已应用自定义声明,并在更新网络应用程序的.onAuthStateChanged
方法后重新登录:
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
firebase.auth().currentUser.getIdToken()
.then((idToken) => {
// Parse the ID token.
const payload = JSON.parse(window.atob(idToken.split('.')[1]));
// Confirm the user is an Admin.
if (!!payload['admin']) {
//showAdminUI();
console.log("we ARE an admin");
}
else {
console.log("we ARE NOT an admin");
}
})
.catch((error) => {
console.log(error);
});
}
else {
//USER IS NOT SIGNED IN
}
});