Teste o Cloud Firestore: conheça o banco de dados escalonável e flexível do Firebase e do Google Cloud Platform. Saiba mais sobre o Cloud Firestore.

Segurança baseada no usuário

Neste documento, recapitulamos os conceitos sobre Como proteger seus dados usando a variável auth predefinida para criar uma solução completa de proteção aos nossos dados.

Integração do Authentication

O Firebase Authentication se integra ao Firebase Realtime Database para permitir que você controle o acesso de cada usuário aos dados.

Quando um usuário se autenticar, a variável auth nas suas regras do Firebase Database será preenchida com as informações do usuário. Essas informações incluem o identificador exclusivo (uid) e os dados da conta vinculada, como um código do Facebook ou um endereço de e-mail, e outras informações. Se você implementar um provedor de autenticação personalizado, será possível adicionar seus próprios campos ao payload de autenticação do seu usuário.

Este guia explica como combinar a linguagem das regras do Firebase Realtime Database com informações de autenticação sobre seus usuários. Ao combinar esses dois conceitos, você pode controlar o acesso aos dados com base na identidade do usuário.

Variável auth

A variável auth predefinida nas regras é nula antes da autenticação. Quando um usuário é autenticado com o Firebase Authentication, ele recebe os seguintes atributos:

provider O método de autenticação utilizado ("senha", "anônimo", "facebook", "github", "google" ou "twitter").
uid Um código de usuário único em todos os provedores.
token O conteúdo do token de código do Firebase Auth. Consulte a documentação de referência do auth.token para ver mais detalhes.

Veja um exemplo de regra que usa a variável auth para garantir que cada usuário só possa gravar em um caminho específico:

{
  "rules": {
    "users": {
      "$user_id": {
        // grants write access to the owner of this user account
        // whose uid must exactly match the key ($user_id)
        ".write": "$user_id === auth.uid"
      }
    }
  }
}

Estruturar seu banco de dados

Às vezes, é útil estruturar o banco de dados de forma a facilitar a gravação de regras de segurança. Por exemplo, um padrão comum para armazenar dados do usuário no Realtime Database é armazenar todos os usuários em um node users cujos filhos são os valores uid de cada usuário. Se você quiser restringir o acesso a esses dados para que apenas o usuário conectado os veja, as regras seriam semelhantes a:

{
  "rules": {
    "users": {
      "$uid": {
        ".read": "auth != null && auth.uid == $uid"
      }
    }
  }
}

Trabalhar com declarações personalizadas de autenticação

Para aplicativos que exigem controle de acesso personalizado para diferentes usuários, o Firebase Authentication permite que os desenvolvedores definam declarações em um usuário do Firebase. Essas declarações são acessíveis na variável auth.token nas suas regras. Veja um exemplo de regras que usam a declaração personalizada hasEmergencyTowel:

{
  "rules": {
    "frood": {
      // A towel is about the most massively useful thing an interstellar
      // hitchhiker can have
      ".read": "auth.token.hasEmergencyTowel === true"
    }
  }
}

Desenvolvedores que criam os próprios tokens de autenticação personalizados podem incluir declarações neles. Essas declarações estão disponíveis na variável auth.token nas suas regras.

Recapitular o exemplo de bate-papo

Vamos continuar analisando o exemplo do bate-papo apresentado em Como proteger seus dados e adicionar autenticação do usuário, reunindo todos esses conceitos em um app funcional:

{
  "rules": {
    "room_names": {
      // any logged in user can get a list of room names
      ".read": "auth !== null",

      "$room_id": {
        // this is just for documenting the structure of rooms, since
        // they are read-only and no write rule allows this to be set
        ".validate": "newData.isString()"
      }
    },

    "members": {
       // I can join or leave any room (otherwise it would be a boring demo)
       // I can have a different name in each room just for fun
       "$room_id": {
          // any member can read the list of member names
          ".read": "data.child(auth.uid).exists()",

          // room must already exist to add a member
          ".validate": "root.child('room_names/'+$room_id).exists()",

          "$user_id": {
             ".write": "auth.uid === $user_id",
             ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 20"
          }
       }
    },

    "messages": {
      "$room_id": {
        // the list of messages for a room can be read by any member
        ".read": "root.child('members/'+$room_id+'/'+auth.uid).exists()",

        // room we want to write a message to must be valid
        ".validate": "root.child('room_names/'+$room_id).exists()",

        "$message_id": {
          // a new message can be created if it does not exist, but it
          // cannot be modified or deleted
          // any member of a room can write a new message
          ".write": "root.child('members/'+$room_id+'/'+auth.uid).exists() && !data.exists() && newData.exists()",

          // the room attribute must be a valid key in room_names/ (the room must exist)
          // the object to write must have a name, message, and timestamp
          ".validate": "newData.hasChildren(['user', 'message', 'timestamp'])",

          // the message must be written by logged in user
          "user": {
             ".validate": "newData.val() === auth.uid"
          },

          // the message must be longer than 0 chars and less than 50
          "message": { ".validate": "newData.isString() && newData.val().length > 0 && newData.val().length < 50" },

          // messages cannot be added in the past or the future
          // clients should use firebase.database.ServerValue.TIMESTAMP
          // to ensure accurate timestamps
          "timestamp": { ".validate": "newData.val() <= now" },

          // no other fields can be included in a message
          "$other": { ".validate": false }
        }
      }
    }
  }
}

Próximas etapas

Enviar comentários sobre…

Firebase Realtime Database
Precisa de ajuda? Acesse nossa página de suporte.