[英]Firestore Realtime Database authentication rules
给定以下数据结构:
无论如何,是否可以根据条目的复合键中 auth.uid 的存在来验证读取请求? 例如“5f6d9d83258b65b5f272aa9f|5f79b99dc6a7c11b9c0eab78”中的“5f79b99dc6a7c11b9c0eab78”?
我试过这个 - 但我假设 contains 与条目中的字段相关,而不是密钥本身。
{
"rules": {
"messages": {
"$message": {
".read": "$message.contains(auth.uid)"
}
}
}
}
编辑:
这是我对用户进行身份验证、预取现有消息(我将在此处添加一些进一步的逻辑以一次仅提取 X 条消息)、发送和检索新消息的代码。
import * as firebase from "firebase/app";
import "firebase/auth";
import "firebase/database";
export const initClient = async (token) => {
if (!firebase.apps.length) {
var firebaseConfig = {
apiKey: "[API]",
authDomain: "[DOMAIN]",
databaseURL: "[URL]",
projectId: "[ID]",
storageBucket: "[STORAGE]",
messagingSenderId: "[SENDERID]",
appId: "[APP_ID]",
measurementId: "[MEAS_ID]"
};
firebase.initializeApp(firebaseConfig);
await firebase.auth().signInWithCustomToken(token).catch(function (error) {
var errorCode = error.code;
var errorMessage = error.message;
//todo
});
return { authenticated: true }
}
}
export const writeMessage = (fromId, chatId, message) => {
var newMessageKey = firebase.database().ref().child('messages/' + chatId).push().key;
firebase.database().ref('messages/' + chatId + '/' + newMessageKey).set({
senderId: fromId,
message: encodeURIComponent(message)
});
}
//get all messages once when a particular chat window is open - works fine without auth rules in place
export const getMessages = async (chatId) => {
//chatId = '5f6d9d83258b65b5f272aa9f|5f79b99dc6a7c11b9c0eab78
var ref = firebase.database().ref('messages/' + chatId);
const snapshot = await ref.once('value')
const messages = snapshot.val();
const messagesArray = Object.keys(messages).map(key => ({ ...messages[key], message: decodeURIComponent(messages[key].message), messageId: key }))
return { chatId, messages: messagesArray };
}
let bound = false;
//set listeners to get new messages and pass the messages back into the application
export const setMessageListeners = async (chatId, onNewMessage) => {
if(bound) return;
bound = true;
var ref = firebase.database().ref('messages/' + chatId);
ref.endAt().limitToLast(1).on('child_added', function (data) {
onNewMessage(chatId, data.key, decodeURIComponent(data.val().message), data.val().senderId);
});
}
也许我需要为每个请求对自定义令牌做些什么?
我可能应该注意到,我也无法获得在规则编辑器游乐场内玩球的规则。 毫无疑问,它与我用来测试的有效载荷有关。
除此之外,我有一些服务器端逻辑来跟踪每个对话,这些数据实际上存储在 RTDB 之外——上面纯粹是一个消息存储。
编辑:排序!
{
"rules": {
"messages": {
"$conversation": {
".read": "$conversation.contains(auth.uid)",
"$message": {
".write": "newData.child('senderId').val() === auth.uid && !data.exists() || data.child('senderId').val() === auth.uid && data.exists()"
}
}
}
}
}
看来我的问题实际上根本不是问题。 只是我错误地使用了 playground,并在与规则集中的动态键匹配的路径段中添加了花括号(不知道为什么,但我确定我在某处看到过)。 上面的结构是我现在确定的。 参与对话的任何人都可以阅读消息(直到我添加已删除的属性,而不是删除消息我只是隐藏它)。 如果新项目不存在,您可以编写它们,或者更新属于您的现有消息。
谢谢你的帮助!
我只是尝试重现这个问题,但它似乎对我来说工作正常。 我将在下面分享我的代码、数据和规则,希望它们能帮助您找到问题/差异。
我的JSON:
{
"anotheruser-m4yXaC9wmCdJXOiL2LDPEJDPoHw1" : "value2",
"m4yXaC9wmCdJXOiL2LDPEJDPoHw1-anotheruser" : "value1"
}
我的代码:
firebase.auth().signInAnonymously();
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log("uid: "+user.uid);
var ref = firebase.database().ref("64258893");
ref.child("m4yXaC9wmCdJXOiL2LDPEJDPoHw1-anotheruser").once("value")
.then(function(snapshot) {
console.log(snapshot.key+": "+snapshot.val());
}).catch(function(error) {
console.error(error);
});
}
});
我对节点64258893
的安全规则:
{
"rules": {
"64258893": {
"$message": {
".read": "$message.contains(auth.uid)"
}
},
...
此代码记录:
“uid:m4yXaC9wmCdJXOiL2LDPEJDPoHw1”
“m4yXaC9wmCdJXOiL2LDPEJDPoHw1-另一个用户:value1”
这正是我所期望的,因为您可以看到 UID 嵌入在密钥中。 如果我将读取更改为不包含 UID 的其他路径(如ref.child("yes-anotheruser")
,则读取将被拒绝。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.