Обновление 2019-11-03: добавлено живое минимальное воспроизведение ошибки . После загрузки ссылки в Chrome нажмите Ctrl + Shift + I и выберите консоль, чтобы увидеть вывод. Я изо всех сил старался убедиться, что это именно то, что делает код моего оригинального проекта;посмотрим, так ли это, а? Файл правил для шарда такой же, как и в оригинальном посте ниже. Источник доступен на GitHub .
<!DOCTYPE html>
<html>
<body>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-database.js"></script>
<script>
const config={
apiKey: "AIzaSyDLMc0GUf5n2nQa3aqpELQu7lziprQOGs8",
authDomain: "shardautherror.firebaseapp.com",
databaseURL: "https://shardautherror.firebaseio.com",
projectId: "shardautherror",
storageBucket: "shardautherror.appspot.com",
messagingSenderId: "841096336504",
appId: "1:841096336504:web:9899961c8250caa552498d"
};
const shard="https://shardautherror-1e9ed.firebaseio.com/";
async function init(){
try{
firebase.database.enableLogging(true);
const defaultApp=firebase.initializeApp(config);
const auth=defaultApp.auth();
const s="alice@example.com";
await auth.signInWithEmailAndPassword(s,s);
const uid= auth.currentUser.uid;
const shardApp=firebase.initializeApp({databaseURL:shard},'dbAppShard');
const db=firebase.database(shardApp);
const ref= db.ref("/chat/"+uid+"/fail/"+uid);
const time= firebase.database.ServerValue.TIMESTAMP;
ref.set({time});
} catch(e) {
console.error("init failed",e);
}
}
init();
</script>
</body>
</html>
Исходное сообщение:
Эти правила работают в симуляторе, но не в моем реальном веб-приложении. Путь и полезная нагрузка симулятора такие же, как показано в выходных данных журнала базы данных ниже.
database.rules.json
(main
предназначается для обоих шардов, чтобы использовать этот файл правил; я проверял при развертывании)
{
"rules":{
"chat":{
"$ownerId":{
"fail":{
"$pId":{
".write": "$pId== auth.uid&& $ownerId== auth.uid",
"time":{".validate": "newData.val()== now"},
"$other":{".validate": "newData.isString()&& newData.val().length>= 28"}
}
}
}
}
}
}
Выход из журнала Firebase сбоя команды set. Он просто записывает одно значение, называемое временем. Я впервые пытаюсь использовать rtdb. Я настроил это с помощью шардинга. Он получает имя осколка от firestore прямо перед попыткой доступа к базе данных в реальном времени, но это не похоже на состояние гонки (несмотря на вывод журнала) по причинам, которые я обрисую ниже.
index.esm.js:81 [2019-10-19T03:02:53.281Z] @firebase/database: 0: set
{"path":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
"value":{"time":{".sv":"timestamp"}},"priority":null}
22:02:53.285 index.esm.js:81 [2019-10-19T03:02:53.285Z] @firebase/database:
p:0: Buffering put: /chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3
22:02:53.293 index.esm.js:81 [2019-10-19T03:02:53.293Z] @firebase/database:
p:0: Making a connection attempt
22:02:53.294 index.esm.js:81 [2019-10-19T03:02:53.294Z] @firebase/database:
getToken() completed. Creating connection.
22:02:53.295 index.esm.js:81 [2019-10-19T03:02:53.295Z] @firebase/database:
c:0:0: Connection created
22:02:53.296 index.esm.js:81 [2019-10-19T03:02:53.296Z] @firebase/database:
p:0: Auth token refreshed
22:02:53.298 index.esm.js:81 [2019-10-19T03:02:53.298Z] @firebase/database:
c:0:0:0 Websocket connecting to wss://quickstart-1551998385825-7f7a6.firebaseio.com/.ws?v=5
22:02:53.534 index.esm.js:81 [2019-10-19T03:02:53.534Z] @firebase/database:
c:0:0:0 Websocket connected.
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z] @firebase/database:
c:0:0: Realtime connection established.
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z] @firebase/database:
p:0: connection ready
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.541Z] @firebase/database:
p:0: reportStats {"c":{"sdk.js.7-0-0":1}}
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.542Z] @firebase/database:
p:0: {"r":1,"a":"s","b":{"c":{"sdk.js.7-0-0":1}}}
22:02:53.546 index.esm.js:81 [2019-10-19T03:02:53.546Z] @firebase/database:
p:0: {"r":2,"a":"p","b":{"p":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
"d":{"time":{".sv":"timestamp"}}}}
22:02:53.591 index.esm.js:81 [2019-10-19T03:02:53.591Z] @firebase/database:
p:0: from server: {"r":1,"b":{"s":"ok","d":""}}
22:02:53.595 index.esm.js:81 [2019-10-19T03:02:53.595Z] @firebase/database:
c:0:0: Primary connection is healthy.
22:02:53.596 index.esm.js:81 [2019-10-19T03:02:53.596Z] @firebase/database:
p:0: from server: {"r":2,"b":{"s":"permission_denied","d":"Permission denied"}}
22:02:53.597 index.esm.js:81 [2019-10-19T03:02:53.597Z] @firebase/database:
p:0: p response {"s":"permission_denied","d":"Permission denied"}
Итакпосле этого, если я обновлю правило до ".write": true,
, запись метки времени будет успешной. В журнале он показывает "r":3 ...
, поэтому я знаю, что он не выбрасывал соединение и перезапускал. Если я затем изменю его на ".write": "auth.uid != null",
или ".write": "auth != null",
(таким образом, не проверяя владение, просто войдет ли клиент, в отличие от вышеупомянутого), он снова отклоняет разрешение с "r":4 ..."
, указывающим 4-й запрос. Итак, похоже, что у меня полный сбой при аутентификации клиента в шарде.
Выход симулятора:
Рекомендации? Я уверен, что делаю что-то не так.
Кстати, пользовательская документация повсюду ... Действительно ли все они действительны?
"baskets": {
".read": "auth.uid != null &&// auth.uid!= null from https://firebase.google.com/docs/database/security/securing-data
".read": "auth != null && auth.uid == $uid" // auth != null from https://firebase.google.com/docs/database/security/user-security
".write": "$user_id === auth.uid" // triple equal from https://firebase.google.com/docs/database/security/user-security
".write": "request.auth.uid == uid" // request.auth from realtime database tab of content owner access from https://firebase.google.com/docs/rules/basics