Regole di sicurezza di base

Firebase Security Rules ti consentono di controllare l'accesso ai dati archiviati. La sintassi flessibile delle regole ti consente di creare regole che corrispondono a qualsiasi elemento, da tutte le scritture all'intero database alle operazioni su un documento specifico.

Questa guida descrive alcuni dei casi d'uso più basilari che potresti voler implementare durante la configurazione dell'app e la protezione dei dati. Tuttavia, prima di iniziare a scrivere le regole, ti consigliamo di scoprire di più sul linguaggio in cui sono scritte e sul loro comportamento.

Per accedere alle regole e aggiornarle, segui i passaggi descritti in Gestire e implementare Firebase Security Rules.

Regole predefinite: modalità bloccata

Quando crei un'istanza di database o di archiviazione nella console Firebase, scegli se le Firebase Security Rules devono limitare l'accesso ai dati (modalità bloccata) o consentire l'accesso a chiunque (modalità di test). In Cloud Firestore e Realtime Database, le regole predefinite per la modalità bloccata negano l'accesso a tutti gli utenti. In Cloud Storage, solo gli utenti autenticati possono accedere ai bucket di archiviazione.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Realtime Database

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

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}

Regole dell'ambiente di sviluppo

Mentre lavori alla tua app, potresti voler avere un accesso relativamente aperto o illimitato ai tuoi dati. Assicurati di aggiornare le Security Rules prima di implementare l'app in produzione. Ricorda inoltre che, se implementi l'app, è accessibile pubblicamente, anche se non l'hai lanciata.

Tieni presente che Firebase consente ai client l'accesso diretto ai tuoi dati e che Firebase Security Rules sono l'unica protezione che blocca l'accesso agli utenti malintenzionati. La definizione delle regole separatamente dalla logica del prodotto presenta una serie di vantaggi: i client non sono responsabili dell'applicazione della sicurezza, le implementazioni difettose non compromettono i dati e, soprattutto, non fai affidamento su un server intermedio per proteggere i dati dal mondo.

Tutti gli utenti autenticati

Sebbene non consigliamo di lasciare i dati accessibili a qualsiasi utente che ha eseguito l'accesso, potrebbe essere utile impostare l'accesso a qualsiasi utente autenticato durante lo sviluppo dell'app.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    match /some_collection/{document} {
      allow read, write: if request.auth != null;
    }
  }
}

Realtime Database

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

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    match /some_folder/{fileName} {
      allow read, write: if request.auth != null;
    }
  }
}

Regole pronte per la produzione

Quando ti prepari a implementare l'app, assicurati che i dati siano protetti e che l'accesso sia concesso correttamente agli utenti. Utilizza Authentication per configurare l'accesso basato sull'utente e leggi direttamente dal database per configurare l'accesso basato sui dati.

Valuta la possibilità di scrivere le regole mentre strutturi i dati, poiché il modo in cui le configuri influisce sulla limitazione dell'accesso ai dati in percorsi diversi.

Accesso solo al proprietario dei contenuti

Queste regole limitano l'accesso solo al proprietario autenticato dei contenuti. I dati sono leggibili e scrivibili solo da un utente e il percorso dei dati contiene l'ID utente.

Quando questa regola funziona: questa regola funziona bene se i dati sono isolati per utente, ovvero se l'unico utente che deve accedere ai dati è lo stesso utente che li ha creati.

Quando questa regola non funziona: questo insieme di regole non funziona quando più utenti devono scrivere o leggere gli stessi dati: gli utenti sovrascriveranno i dati o non potranno accedere ai dati che hanno creato.

Per configurare questa regola: crea una regola che confermi che l'utente che richiede l'accesso in lettura o scrittura ai dati è l'utente proprietario di questi dati.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{document} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Allow only authenticated content owners access to their data
        ".read": "auth !== null && auth.uid === $uid",
        ".write": "auth !== null && auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

// Grants a user access to a node matching their user ID
service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read, write: if request.auth != null && request.auth.uid == userId;
    }
  }
}

Accesso pubblico e privato misto

Questa regola consente a chiunque di leggere un set di dati, ma limita la possibilità di creare o modificare i dati in un determinato percorso solo al proprietario dei contenuti autenticato.

Quando questa regola funziona: questa regola funziona bene per le app che richiedono elementi leggibili pubblicamente, ma devono limitare l'accesso in modifica ai proprietari di questi elementi. Ad esempio, un'app di chat o un blog.

Quando questa regola non funziona: come la regola solo per il proprietario dei contenuti, questo insieme di regole non funziona quando più utenti devono modificare gli stessi dati. Gli utenti finiranno per sovrascrivere i dati degli altri.

Per configurare questa regola: crea una regola che attivi l'accesso in lettura per tutti gli utenti (o tutti gli utenti autenticati) e confermi che l'utente che scrive i dati è il proprietario.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow public read access, but only content owners can write
    match /some_collection/{document} {
      // Allow public reads
      allow read: if true
      // Allow creation if the current user owns the new document
      allow create: if request.auth.uid == request.resource.data.author_uid;
      // Allow updates by the owner, and prevent change of ownership
      allow update: if request.auth.uid == request.resource.data.author_uid
                    && request.auth.uid == resource.data.author_uid;
      // Allow deletion if the current user owns the existing document
      allow delete: if request.auth.uid == resource.data.author_uid;
    }
  }
}

Realtime Database

{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data

  "rules": {
    "some_path": {
      "$uid": {
        ".read": true,
        // or ".read": "auth.uid !== null" for only authenticated users
        ".write": "auth.uid === $uid"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  match /b/{bucket}/o {
    // Files look like: "user/<UID>/file.txt"
    match /user/{userId}/{fileName} {
      allow read;
      allow write: if request.auth.uid == userId;
    }
  }
}

Accesso basato su attributi e ruoli

Affinché queste regole funzionino, devi definire e assegnare attributi agli utenti nei tuoi dati. Firebase Security Rules controllano la richiesta rispetto ai dati dei metadati del database o del file per confermare o negare l'accesso.

Quando questa regola funziona: se assegni un ruolo agli utenti, questa regola ti consente di limitare l'accesso in base ai ruoli o a gruppi specifici di utenti. Ad esempio, se memorizzassi i voti, potresti assegnare livelli di accesso diversi al gruppo "studenti" (solo lettura dei contenuti), al gruppo "insegnanti" (lettura e scrittura nella materia) e al gruppo "dirigenti" (lettura di tutti i contenuti).

Quando questa regola non funziona: In Realtime Database e Cloud Storage, le regole non possono utilizzare il metodo get() che le regole di Cloud Firestore possono incorporare. Di conseguenza, devi strutturare i metadati del database o del file in modo che riflettano gli attributi che utilizzi nelle regole.

Per configurare questa regola: In Cloud Firestore, includi un campo nei documenti degli utenti che puoi leggere, quindi struttura la regola in modo che legga il campo e conceda l'accesso in modo condizionale. In Realtime Database, crea un percorso dei dati che definisca gli utenti dell'app e assegna loro un ruolo in un nodo figlio.

Puoi anche configurare rivendicazioni personalizzate in Authentication e poi recuperare queste informazioni dalla auth.token variabile in qualsiasi Firebase Security Rules.

Attributi e ruoli definiti dai dati

Queste regole funzionano solo in Cloud Firestore e Realtime Database.

Cloud Firestore

Tieni presente che ogni volta che le regole includono una lettura, come le regole riportate di seguito, ti viene addebitata un'operazione di lettura in Cloud Firestore.

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
     allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "${subpath}": {
        //
        ".write": "root.child('users').child(auth.uid).child('role').val() === 'admin'",
        ".read": true
      }
    }
  }
}

Attributi e ruoli delle rivendicazioni personalizzate

Per implementare queste regole, configura le rivendicazioni personalizzate in Firebase Authentication e poi utilizza le rivendicazioni nelle regole.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, check for an administrator claim
    allow write: if request.auth.token.admin == true;
    allow read: true;

    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
     allow read: if request.auth.token.reader == "true";
     allow write: if request.auth.token.writer == "true";
   }
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Create a custom claim for each role or group
        // you want to use
        ".write": "auth.uid !== null && auth.token.writer === true",
        ".read": "auth.uid !== null && auth.token.reader === true"
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Allow reads if the group ID in your token matches the file metadata's `owner` property
  // Allow writes if the group ID is in the user's custom token
  match /files/{groupId}/{fileName} {
    allow read: if resource.metadata.owner == request.auth.token.groupId;
    allow write: if request.auth.token.groupId == groupId;
  }
}

Attributi di tenancy

Per implementare queste regole, configura la multi-tenancy in Google Cloud Identity Platform (GCIP) e poi utilizza il tenant nelle regole. Gli esempi seguenti consentono le scritture da parte di un utente in un tenant specifico, ad esempio tenant2-m6tyz.

Cloud Firestore

service cloud.firestore {
  match /databases/{database}/documents {
    // For tenant-based access control, check for a tenantID
    allow write: if request.auth.token.firebase.tenant == 'tenant2-m6tyz';
    allow read: true;
  }
}

Realtime Database

{
  "rules": {
    "some_path": {
      "$uid": {
        // Only allow reads and writes if user belongs to a specific tenant
        ".write": "auth.uid !== null && auth.token.firebase.tenant === 'tenant2-m6tyz'",
        ".read": "auth.uid !== null
      }
    }
  }
}

Cloud Storage

service firebase.storage {
  // Only allow reads and writes if user belongs to a specific tenant
  match /files/{tenantId}/{fileName} {
    allow read: if request.auth != null;
    allow write: if request.auth.token.firebase.tenant == tenantId;
  }
}