правила шардинга базы данных в реальном времени - PullRequest
0 голосов
/ 19 октября 2019

Обновление 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-й запрос. Итак, похоже, что у меня полный сбой при аутентификации клиента в шарде.

Выход симулятора: simulator shows success with the same rules

Рекомендации? Я уверен, что делаю что-то не так.

Кстати, пользовательская документация повсюду ... Действительно ли все они действительны?

"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

Ответы [ 2 ]

0 голосов
/ 13 ноября 2019

Эта строка:

const shardApp=firebase.initializeApp({databaseURL:shard},'dbAppShard');

должна измениться на:

const shardApp=firebase.initializeApp({...config,databaseURL:shard},'dbAppShard');

В текущей документации о защите базы данных только клиент передает только параметр databaseURL для initializeApp, что недостаточно для работы с правилами на основе аутентификации. В отличие от этого Функции администратора отвечают , и этого вступительного сообщения блога со старым синтаксисом для нескольких баз данных , текущие документы требуют, чтобы клиент создавал и управлял несколькими объектами приложения. Как выяснилось в поддержке Firebase, приложения не по умолчанию в настоящее время не извлекают ключ API и другие параметры из объекта приложения по умолчанию (он же первое приложение, созданное без второго аргумента для initializeApp).

0 голосов
/ 19 октября 2019

Здесь есть два вопроса, и первая часть вопроса нуждается в дополнительной информации.

Вторая часть вопроса

Кстати, пользовательская документация законченаместо ... Действительно ли все это действительно?

Документация на самом деле не везде. Каждый из включенных вами примеров правил был из другого варианта использования.

Например, правило .read в «корзинах» применяется к этому конкретному узлу «корзины», гарантируя, что только проверенные пользователи могут читать узел корзин. И это позволит любому авторизованному пользователю прочитать этот узел. В этой строке есть дополнительный &&, поэтому не уверены, какой была оставшаяся часть правила.

Второе правило чтения будет применяться к любому узлу, в котором он находится, и будет гарантировать, что пользователь аутентифицирован и что только аутентифицированный пользователь можетчитать этот узел (т. е. это его узел, и никто другой не может получить к нему доступ)

Для записи === (тройное равенство) описано в документации и говорит

Примечание :: == ЛЕЧИТСЯ КАК ===. Если вы используете == в своих правилах безопасности, он будет переведен в === при выполнении правил.

Последняя запись просто проверяет, что uid запроса является в настоящий момент auth 'Пользователь d.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...