Firebase Security Rules ti consentono di controllare l'accesso ai dati archiviati. La sintassi delle regole flessibili consente di creare regole che corrispondono a qualsiasi cosa, da tutte le scritture nell'intero database alle operazioni su un documento specifico.
Questa guida descrive alcuni dei casi d'uso più di base che potresti voler implementare durante la configurazione dell'app e la salvaguardia 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 e aggiornare le regole, segui i passaggi descritti in Gestire ed eseguire il deployment di Firebase Security Rules.
Regole predefinite: modalità di blocco
Quando crei un database o un'istanza di archiviazione nella console Firebase, scegli se Firebase Security Rules limitare l'accesso ai tuoi dati (Modalità di blocco) o consentire l'accesso a chiunque (Modalità di test). In Cloud Firestore e Realtime Database, le regole predefinite per la modalità di blocco 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 request.auth != null;
}
}
}
Regole per l'ambiente di sviluppo
Mentre lavori alla tua app, potresti volere un accesso relativamente aperto o illimitato ai tuoi dati. Assicurati solo di aggiornare Rules prima di eseguire il deployment dell'app in produzione. Ricorda inoltre che se esegui il deployment dell'app, questa è accessibile pubblicamente, anche se non l'hai avviata.
Ricorda che Firebase consente ai client l'accesso diretto ai tuoi dati e Firebase Security Rules sono l'unica salvaguardia che blocca l'accesso per gli utenti malintenzionati. La definizione delle regole separatamente dalla logica del prodotto presenta una serie di vantaggi: i clienti non sono responsabili dell'applicazione della sicurezza, le implementazioni con bug non comprometteranno i tuoi dati e, soprattutto, non farai affidamento su un server intermediario per proteggere i dati da tutto il mondo.
Tutti gli utenti autenticati
Sebbene non sia consigliabile 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 /{document=**} {
allow read, write: if request.auth != null;
}
}
}
Realtime Database
{
"rules": {
".read": "auth.uid !== null",
".write": "auth.uid !== null"
}
}
Cloud Storage
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Regole pronte per la produzione
Quando ti prepari a eseguire il deployment dell'app, assicurati che i tuoi dati siano protetti e che l'accesso sia concesso correttamente agli utenti. Utilizza Authentication per configurare l'accesso in base all'utente e per leggere direttamente dal tuo database per configurare l'accesso in base ai dati.
Valuta la possibilità di scrivere le regole quando strutturi i dati, poiché il modo in cui configuri le regole influisce sulla limitazione dell'accesso ai dati su percorsi diversi.
Accesso solo per 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 dell'utente.
Quando funziona questa regola: questa regola funziona bene se i dati sono silos per utente, ovvero se l'unico utente che deve accedere ai dati è lo stesso 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 per leggere o scrivere i dati sia l'utente proprietario dei dati.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /some_collection/{userId}/{documents=**} {
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>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read, write: if request.auth != null && request.auth.uid == userId;
}
}
}
Accesso misto pubblico e privato
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 funziona questa regola: questa regola è ideale per le app che richiedono elementi pubblicamente disponibili, 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, questa serie di regole non funziona quando più utenti devono modificare gli stessi dati. Gli utenti alla fine sovrascriveranno i dati l'uno dell'altro.
Per impostare questa regola: crea una regola che consenta l'accesso in lettura per tutti gli utenti (o tutti gli utenti autenticati) e verifichi che l'utente che scrive i dati sia 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>/path/to/file.txt"
match /user/{userId}/{allPaths=**} {
allow read;
allow write: if request.auth.uid == userId;
}
}
}
Accesso basato su attributi e su ruoli
Affinché queste regole funzionino, devi definire e assegnare gli attributi agli utenti nei tuoi dati. Firebase Security Rules confronta la richiesta con i dati del database o dei metadati del file per confermare o negare l'accesso.
Quando funziona questa regola: se assegni un ruolo agli utenti, questa regola consente di limitare facilmente l'accesso in base ai ruoli o a gruppi specifici di utenti. Ad esempio, se memorizzi i voti, puoi assegnare livelli di accesso diversi al gruppo "Studenti" (solo lettura dei contenuti), al gruppo "Insegnanti" (lettura e scrittura nel proprio argomento) e al gruppo "Presidi" (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 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 da leggere quel campo e concedere l'accesso in modo condizionale. In Realtime Database, crea un percorso dati che definisca gli utenti della tua app e concedi loro un ruolo in un nodo figlio.
Puoi anche configurare affermazioni personalizzate in Authentication
e poi recuperare queste informazioni dalla variabile
auth.token
in qualsiasi Firebase Security Rules.
Attributi e ruoli definiti dai dati
Queste regole funzionano solo in Cloud Firestore e Realtime Database.
Cloud Firestore
Ricorda che ogni volta che le tue regole includono una lettura, come quelle riportate di seguito, ti viene addebitato 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 i claim personalizzati in Firebase Authentication e poi utilizzali nelle regole.
Cloud Firestore
service cloud.firestore {
match /databases/{database}/documents {
// For attribute-based access control, check for an admin 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 leverage
".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 della proprietà
Per implementare queste regole, configura l'architettura multi-tenancy in Google Cloud Identity Platform (GCIP)
e poi utilizza il tenant nelle regole. I seguenti esempi consentono le scritture
da 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;
}
}