Questa pagina è stata tradotta dall'API Cloud Translation.
Switch to English

Sicurezza basata sull'utente

Questo documento rivisita i concetti di Protezione dei dati , incorporando la variabile di auth predefinita per creare una soluzione completa per la protezione dei nostri dati.

Autenticazione integrata

L'autenticazione Firebase si integra con il database in tempo reale di Firebase per consentire all'utente di controllare l'accesso ai dati per utente.

Una volta autenticato un utente, la variabile di auth nelle regole delle Regole del database in tempo reale verrà popolata con le informazioni dell'utente. Queste informazioni includono il loro identificatore univoco ( uid ) nonché i dati dell'account collegato, come un ID Facebook o un indirizzo e-mail e altre informazioni. Se si implementa un provider di autenticazione personalizzato, è possibile aggiungere i propri campi al payload di autenticazione dell'utente.

Questa guida spiega come combinare il linguaggio delle regole del database in tempo reale di Firebase con le informazioni di autenticazione relative agli utenti. Combinando questi due concetti, è possibile controllare l'accesso ai dati in base all'identità dell'utente.

La variabile auth

La variabile di auth predefinita nelle regole è nulla prima che abbia luogo l'autenticazione. Una volta che un utente è autenticato con Firebase Authentication , conterrà i seguenti attributi:

fornitore Il metodo di autenticazione utilizzato ("password", "anonimo", "facebook", "github", "google" o "twitter").
uid Un ID utente unico, garantito per essere unico per tutti i provider.
gettone Il contenuto del token ID autenticazione Firebase. Vedere la documentazione di riferimento per auth.token per maggiori dettagli.

Ecco una regola di esempio che utilizza la variabile auth per garantire che ogni utente possa scrivere solo in un percorso specifico dell'utente:

{
  "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"
      }
    }
  }
}

Strutturare il tuo database

A volte è utile strutturare il database in modo da facilitare la scrittura delle regole di sicurezza. Ad esempio, un modello comune per l'archiviazione dei dati utente nel database in tempo reale è l'archiviazione di tutti i tuoi utenti in un singolo nodo users cui figli sono i valori uid per ogni utente. Se si desidera limitare l'accesso a questi dati in modo tale che solo l'utente che ha effettuato l'accesso possa visualizzare i propri dati, le regole saranno simili al seguente:

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

Lavorare con i reclami personalizzati di autenticazione

Per le app che richiedono il controllo dell'accesso personalizzato per utenti diversi, Firebase Authentication consente agli sviluppatori di impostare attestazioni su un utente Firebase . Queste affermazioni sono accessibili nella variabile auth.token nelle tue regole. Ecco un esempio di regole che fanno uso del hasEmergencyTowel personalizzato hasEmergencyTowel :

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

Gli sviluppatori che creano i propri token di autenticazione personalizzati possono facoltativamente aggiungere attestazioni a questi token. Queste affermazioni sono disponibili sulla variabile auth.token nelle tue regole.

Rivisitare l'esempio di chat

Basiamoci sull'esempio di chat di Protezione dei dati e aggiungiamo alcune autenticazioni dell'utente, riunendo tutti questi concetti in un'app funzionante:

{
  "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 }
        }
      }
    }
  }
}

Prossimi passi