给出以下数据结构:
是否仍然根据条目的复合键中auth.uid的存在来验证读取请求?例如“ 5f6d9d83258b65b5f272aa9f | 5f79b99dc6a7c11b9c0eab78”中的“ 5f79b99dc6a7c11b9c0eab78”?
我已经尝试过-但是我认为包含包含与条目中的字段相关,而不是键本身。
{
"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()"
}
}
}
}
}
看来我的问题根本不是问题。只是我错误地使用了操场,并在与规则集中的动态键匹配的路径段中添加了花括号(不知道为什么,但是我确定我在某处看到了它)。上面的结构是我现在确定的。参与对话的任何人都可以阅读消息(直到我添加一个已删除的属性,而不是删除消息后我才会将其隐藏)。您可以编写不存在的新项目,也可以更新属于您的现有邮件。
感谢您的帮助!
答案 0 :(得分:1)
我只是尝试重现此问题,但它似乎对我来说很好。我将在下面分享我的代码,数据和规则,希望它们能帮助您找到问题/差异。
我的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")
,那么读取将被拒绝。