В разрешении Firebase отказано

125

Я относительно новичок в программировании, и у меня проблемы.

У меня есть этот код для отправки данных в firebase

app.userid = app.user.uid

var userRef = app.dataInfo.child(app.users);

var useridRef = userRef.child(app.userid);

useridRef.set({
  locations: "",
  theme: "",
  colorScheme: "",
  food: ""
});

Однако я продолжаю получать ошибку:

ПРЕДУПРЕЖДЕНИЕ FIREBASE: установить в / users / (GoogleID) не удалось: permission_denied 2016-05-23 22: 52: 42.707 firebase.js: 227 Не перехвачено (в обещании) Ошибка: PERMISSION_DENIED: Permission denied (…)

Когда я пытаюсь найти это, он говорит о правилах для Firebase, которые, кажется, написаны на языке, который я еще не изучил (или это просто выходит у меня из головы). Может кто-нибудь объяснить, что вызывает проблему? Я думал, что прошу сохранить адрес электронной почты и отображаемое имя пользователя, а вам просто не разрешили это делать, но когда я удалил их, у меня все еще была та же проблема. Есть ли способ избежать этой ошибки, не устанавливая правила, или правила - это то, чему я могу научить себя, как писать за день, или я просто не в своей лиге?

Спасибо за любую помощь!

Роберт Прайн
источник

Ответы:

252

По умолчанию база данных в проекте в Firebase Console доступна для чтения и записи только администраторам (например, в облачных функциях или процессах, использующих Admin SDK). Пользователи обычных клиентских пакетов SDK не могут получить доступ к базе данных, если вы не измените правила безопасности на стороне сервера.


Вы можете изменить правила, чтобы база данных была доступна для чтения и записи только аутентифицированным пользователям:

{
  "rules": {
    ".read": "auth != null",
    ".write": "auth != null"
  }
}

См. Краткое руководство по правилам безопасности базы данных Firebase .

Но поскольку вы не подписываете пользователя из своего кода, база данных отказывает вам в доступе к данным. Чтобы решить эту проблему, вам нужно будет либо разрешить неаутентифицированный доступ к вашей базе данных, либо войти в систему перед доступом к базе данных.

Разрешить неаутентифицированный доступ к вашей базе данных

Самый простой обходной путь на данный момент (пока не будет обновлен учебник) - перейти на панель базы данных в консоли вашего проекта, выбрать вкладку Правила и заменить содержимое этими правилами:

{
  "rules": {
    ".read": true,
    ".write": true
  }
}

Это делает вашу новую базу данных доступной для чтения и записи любому, кто знает URL-адрес базы данных. Убедитесь, что вы снова защитили свою базу данных, прежде чем приступить к производству, иначе кто-то может начать злоупотреблять ею.

Войдите в систему перед доступом к базе данных

Для (немного) более трудоемкого, но более безопасного решения вызовите один из signIn...методов аутентификации Firebase, чтобы убедиться, что пользователь вошел в систему перед доступом к базе данных. Самый простой способ сделать это - использовать анонимную аутентификацию :

firebase.auth().signInAnonymously().catch(function(error) {
  // Handle Errors here.
  var errorCode = error.code;
  var errorMessage = error.message;
  // ...
});

А затем прикрепите своих слушателей при обнаружении входа

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
    var isAnonymous = user.isAnonymous;
    var uid = user.uid;
    var userRef = app.dataInfo.child(app.users);

    var useridRef = userRef.child(app.userid);

    useridRef.set({
      locations: "",
      theme: "",
      colorScheme: "",
      food: ""
    });

  } else {
    // User is signed out.
    // ...
  }
  // ...
});
Франк ван Пуффелен
источник
1
Спасибо - использовал небезопасное исправление и процитировал ваш ответ в ответе на аналогичный вопрос для решения проблем с разрешениями Firebase в этом руководстве по Ember . Но где мы можем добавить (безопасный) анонимный код авторизации?
Дэйв Эверитт
2
OMG идет час. У меня было это там, но значения были ЛОЖНЫ ... Я просто не заметил этого. Изменил их на ИСТИНА и бац, приложение работает так, как вы думаете ...
Энди
OMG, я тоже, не мог понять, почему они не справлялись с разрешениями, когда они оба уже были установлены на false (пока я не прочитал ваш комментарий). да, ошибка нуб., они оба должны быть правдой, когда вы делаете это открытым для публики (читает). Спасибо, что указали на вашу ошибку, вы помогли мне разобраться. Для записи я изменил свое правило на это: ".read": true, и оно начало работать.
contractorwolf
@Andy Спасибо, чувак, то же самое и со мной, и ваш комментарий решил мою проблему;)
Махмудул Хасан Сохаг,
86

Я столкнулся с аналогичной проблемой и обнаружил, что эта ошибка возникла из-за неправильного набора правил для операций чтения / записи для базы данных в реальном времени. По умолчанию Google Firebase в настоящее время загружает облачное хранилище, а не базу данных в реальном времени. Нам нужно перейти в режим реального времени и применить правильные правила.

введите описание изображения здесь

Как мы видим, в нем говорится, что облачный Firestore не база данных реального времени, после переключения на правильную базу данных применяются следующие правила:

{
   "rules": {
       ".read": true,
       ".write": true
     }
 }
просто-быть странно
источник
3
Блин UI! Я потратил целый день, выясняя, почему у меня другие правила ... А ... Это было для "облачного хранилища огня" ... Спасибо!
Алексей Володько
42

Перейдите к упомянутой вами опции «База данных».

  1. Там, в синем заголовке, вы найдете раскрывающийся список с надписью Cloud Firestore Beta.
  2. Измените его на «База данных в реальном времени»
  3. Перейдите в Правила и установите .write .read both в значение true

Скопировано отсюда .

Ахмед Адевале
источник
Я проголосовал против, потому что считаю это плохим советом. Если новичок спрашивает, как открыть входную дверь своего магазина, вы не можете просто порекомендовать ему полностью снять замок. Отключение правил безопасности может привести к катастрофе и потенциально очень дорогостоящим штрафам в случае утечки пользовательских данных (и, скорее всего, это произойдет).
silviot
10

Перейти в базу данных, рядом с заголовком есть 2 варианта:

Cloud Firestore, база данных в реальном времени

Выберите базу данных в реальном времени и перейдите к правилам

Измените правила на true.

Джайвант Нарваде
источник
Я проголосовал против, потому что считаю это плохим советом. Если новичок спрашивает, как открыть входную дверь своего магазина, вы не можете просто порекомендовать ему полностью снять замок. Отключение правил безопасности может привести к катастрофе и потенциально очень дорогостоящим штрафам в случае утечки пользовательских данных (и, скорее всего, это произойдет). Кроме того, это дубликат ответа @ ahmed-adewale.
silviot
4

Хорошо, но вы не хотите открывать всю базу данных в реальном времени! Вам нужно что-то подобное.

{
  /* Visit https://firebase.google.com/docs/database/security to learn more about security rules. */
  "rules": {
    ".read": "auth.uid !=null",
    ".write": "auth.uid !=null"
  }
}

или

{
  "rules": {
    "users": {
      "$uid": {
        ".write": "$uid === auth.uid"
      }
    }
  }
}
Ондржей Бауэр
источник
4
  1. Откройте firebase, выберите базу данных слева.
  2. Теперь в правой части окна выберите [База данных реального времени] и измените правила на:
{
  "rules": {
    ".read": true,
    ".write": true
  }
}
Аниндья Санкар Дасгупта
источник
7
Об этом уже было сказано в другом ответе. Также, когда вы предлагаете это, обязательно добавьте предупреждение, потому что это не сохраняется!
Андре Кул
1

Другое решение - фактически создать пользователя или войти в систему автоматически, если у вас уже есть учетные данные. Вот как я это делаю с помощью Plain JS.

function loginToFirebase(callback)
{
    let email = 'xx@xx.com';
    let password = 'xxxxxxxxxxxxxx';
    let config =
    {
        apiKey: "xxx",
        authDomain: "xxxxx.firebaseapp.com",
        projectId: "xxx-xxx",
        databaseURL: "https://xxx-xxx.firebaseio.com",
        storageBucket: "gs://xx-xx.appspot.com",
    };

    if (!firebase.apps.length)
    {
        firebase.initializeApp(config);
    }

    let database = firebase.database();
    let storage = firebase.storage();

    loginFirebaseUser(email, password, callback);
}

function loginFirebaseUser(email, password, callback)
{
    console.log('Logging in Firebase User');

    firebase.auth().signInWithEmailAndPassword(email, password)
        .then(function ()
        {
            if (callback)
            {
                callback();
            }
        })
        .catch(function(login_error)
        {
            let loginErrorCode = login_error.code;
            let loginErrorMessage = login_error.message;

            console.log(loginErrorCode);
            console.log(loginErrorMessage);

            if (loginErrorCode === 'auth/user-not-found')
            {
                createFirebaseUser(email, password, callback)
            }
        });
}

function createFirebaseUser(email, password, callback)
{
    console.log('Creating Firebase User');

    firebase.auth().createUserWithEmailAndPassword(email, password)
        .then(function ()
        {
            if (callback)
            {
                callback();
            }
        })
        .catch(function(create_error)
        {
            let createErrorCode = create_error.code;
            let createErrorMessage = create_error.message;

            console.log(createErrorCode);
            console.log(createErrorMessage);
        });
}
Parampal Pooni
источник
1
Это действительно плохо с точки зрения безопасности.
ASH