Questa guida si basa sull'apprendimento della sintassi di base della guida linguistica delle regole di sicurezza di Firebase per mostrare come aggiungere condizioni alle regole di sicurezza di Firebase per Cloud Storage.
L'elemento costitutivo principale delle regole di sicurezza di Cloud Storage è la condizione . Una condizione è un'espressione booleana che determina se una particolare operazione deve essere consentita o negata. Per le regole di base, l'utilizzo di valori letterali true
e false
come condizioni funziona perfettamente. Ma il linguaggio Firebase Security Rules for Cloud Storage ti offre modi per scrivere condizioni più complesse che possono:
- Controlla l'autenticazione dell'utente
- Convalida i dati in arrivo
Autenticazione
Firebase Security Rules for Cloud Storage si integra con Firebase Authentication per fornire una potente autenticazione basata sugli utenti a Cloud Storage. Ciò consente un controllo granulare degli accessi basato sulle attestazioni di un token di autenticazione Firebase.
Quando un utente autenticato esegue una richiesta su Cloud Storage, la variabile request.auth
viene popolata con l' uid
dell'utente ( request.auth.uid
) e con le attestazioni del JWT di autenticazione Firebase ( request.auth.token
).
Inoltre, quando si utilizza l'autenticazione personalizzata, vengono visualizzate attestazioni aggiuntive nel campo request.auth.token
.
Quando un utente non autenticato esegue una richiesta, la variabile request.auth
è null
.
Utilizzando questi dati, esistono diversi modi comuni per utilizzare l'autenticazione per proteggere i file:
- Pubblico: ignora
request.auth
- Privato autenticato: verifica che
request.auth
non sianull
- Utente privato: verifica che
request.auth.uid
sia uguale a un pathuid
- Gruppo privato: verifica che le attestazioni del token personalizzato corrispondano a un'attestazione scelta oppure leggi i metadati del file per vedere se esiste un campo di metadati
Pubblico
Qualsiasi regola che non considera il contesto request.auth
può essere considerata una regola public
, poiché non considera il contesto di autenticazione dell'utente. Queste regole possono essere utili per far emergere dati pubblici come risorse di gioco, file audio o altri contenuti statici.
// Anyone to read a public image if the file is less than 100kB // Anyone can upload a public file ending in '.txt' match /public/{imageId} { allow read: if resource.size < 100 * 1024; allow write: if imageId.matches(".*\\.txt"); }
Privato autenticato
In alcuni casi, potresti volere che i dati siano visualizzabili da tutti gli utenti autenticati della tua applicazione, ma non da quelli non autenticati. Poiché la variabile request.auth
è null
per tutti gli utenti non autenticati, tutto ciò che devi fare è controllare che la variabile request.auth
esista per richiedere l'autenticazione:
// Require authentication on all internal image reads match /internal/{imageId} { allow read: if request.auth != null; }
Utente privato
Il caso d'uso di gran lunga più comune per request.auth
sarà quello di fornire ai singoli utenti autorizzazioni granulari sui propri file: dal caricamento di immagini del profilo alla lettura di documenti privati.
Poiché i file in Cloud Storage hanno un "percorso" completo al file, tutto ciò che serve per rendere un file controllato da un utente è una parte di informazioni univoche che identificano l'utente nel prefisso del nome del file (come l' uid
dell'utente) che può essere controllato quando la regola viene valutata:
// Only a user can upload their profile picture, but anyone can view it match /users/{userId}/profilePicture.png { allow read; allow write: if request.auth.uid == userId; }
Gruppo privato
Un altro caso d'uso altrettanto comune sarà quello di consentire autorizzazioni di gruppo su un oggetto, come consentire a più membri del team di collaborare su un documento condiviso. Ci sono diversi approcci per farlo:
- Crea un token personalizzato di autenticazione Firebase che contenga informazioni aggiuntive su un membro del gruppo (come un ID gruppo)
- Includere le informazioni sul gruppo (come un ID gruppo o un elenco di
uid
autorizzati) nei metadati del file
Una volta che questi dati sono stati archiviati nel token o nei metadati del file, è possibile farvi riferimento all'interno di una regola:
// 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; }
Richiedi valutazione
Caricamenti, download, modifiche ai metadati ed eliminazioni vengono valutati utilizzando la request
inviata a Cloud Storage. Oltre all'ID univoco dell'utente e al payload di autenticazione Firebase nell'oggetto request.auth
come descritto sopra, la variabile request
contiene il percorso del file in cui viene eseguita la richiesta, l'ora in cui la richiesta viene ricevuta e il nuovo valore resource
se la richiesta è una scrittura.
L'oggetto request
contiene anche l'ID univoco dell'utente e il payload di autenticazione Firebase nell'oggetto request.auth
, che verrà spiegato ulteriormente nella sezione Sicurezza basata sull'utente dei documenti.
Di seguito è disponibile un elenco completo delle proprietà nell'oggetto request
:
Proprietà | Tipo | Descrizione |
---|---|---|
auth | map<stringa, stringa> | Quando un utente ha effettuato l'accesso, fornisce uid , l'ID univoco dell'utente e token , una mappa delle attestazioni JWT di Firebase Authentication. In caso contrario, sarà null . |
params | map<stringa, stringa> | Mappa contenente i parametri di query della richiesta. |
path | sentiero | path che rappresenta il percorso in cui viene eseguita la richiesta. |
resource | map<stringa, stringa> | Il nuovo valore della risorsa, presente solo nelle richieste write . |
time | timestamp | Un timestamp che rappresenta l'ora del server in cui viene valutata la richiesta. |
Valutazione delle risorse
Quando si valutano le regole, è possibile valutare anche i metadati del file caricato, scaricato, modificato o eliminato. Ciò ti consente di creare regole complesse e potenti che fanno cose come consentire solo il caricamento di file con determinati tipi di contenuto o l'eliminazione solo di file superiori a una certa dimensione.
Le regole di sicurezza di Firebase per Cloud Storage forniscono metadati di file nell'oggetto resource
, che contiene coppie chiave/valore dei metadati emersi in un oggetto Cloud Storage. Queste proprietà possono essere ispezionate su richieste read
o write
per garantire l'integrità dei dati.
Nelle richieste write
(come caricamenti, aggiornamenti di metadati ed eliminazioni), oltre all'oggetto resource
, che contiene metadati di file per il file attualmente esistente nel percorso della richiesta, hai anche la possibilità di utilizzare l'oggetto request.resource
, che contiene un sottoinsieme dei metadati del file da scrivere se la scrittura è consentita. È possibile utilizzare questi due valori per garantire l'integrità dei dati o applicare i vincoli dell'applicazione come il tipo o la dimensione del file.
Di seguito è disponibile un elenco completo delle proprietà nell'oggetto resource
:
Proprietà | Tipo | Descrizione |
---|---|---|
name | corda | Il nome completo dell'oggetto |
bucket | corda | Il nome del bucket in cui risiede questo oggetto. |
generation | int | La generazione dell'oggetto Google Cloud Storage di questo oggetto. |
metageneration | int | La metagenerazione dell'oggetto Google Cloud Storage di questo oggetto. |
size | int | La dimensione dell'oggetto in byte. |
timeCreated | timestamp | Un timestamp che rappresenta l'ora in cui è stato creato un oggetto. |
updated | timestamp | Un timestamp che rappresenta l'ora dell'ultimo aggiornamento di un oggetto. |
md5Hash | corda | Un hash MD5 dell'oggetto. |
crc32c | corda | Un hash crc32c dell'oggetto. |
etag | corda | L'etag associato a questo oggetto. |
contentDisposition | corda | La disposizione del contenuto associata a questo oggetto. |
contentEncoding | corda | La codifica del contenuto associata a questo oggetto. |
contentLanguage | corda | La lingua del contenuto associata a questo oggetto. |
contentType | corda | Il tipo di contenuto associato a questo oggetto. |
metadata | map<stringa, stringa> | Coppie chiave/valore di metadati personalizzati aggiuntivi specificati dallo sviluppatore. |
request.resource
contiene tutti questi elementi ad eccezione di generation
, metageneration
, etag
, timeCreated
e updated
.
Migliora con Cloud Firestore
Puoi accedere ai documenti in Cloud Firestore per valutare altri criteri di autorizzazione.
Utilizzando le funzioni firestore.get()
e firestore.exists()
, le tue regole di sicurezza possono valutare le richieste in arrivo rispetto ai documenti in Cloud Firestore. Le funzioni firestore.get()
e firestore.exists()
prevedono entrambe percorsi di documento completamente specificati. Quando si utilizzano variabili per costruire percorsi per firestore.get()
e firestore.exists()
, è necessario eseguire esplicitamente l'escape delle variabili utilizzando la sintassi $(variable)
.
Nell'esempio seguente, vediamo una regola che limita l'accesso in lettura ai file a quegli utenti che sono membri di club particolari.
service firebase.storage { match /b/{bucket}/o { match /users/{club}/files/{fileId} { allow read: if club in firestore.get(/databases/(default)/documents/users/$(request.auth.id)).memberships } } }Nel prossimo esempio, solo gli amici di un utente possono vedere le proprie foto.
service firebase.storage { match /b/{bucket}/o { match /users/{userId}/photos/{fileId} { allow read: if firestore.exists(/databases/(default)/documents/users/$(userId)/friends/$(request.auth.id)) } } }
Una volta create e salvate le prime regole di sicurezza di Cloud Storage che utilizzano queste funzioni di Cloud Firestore, nella console di Firebase o nella CLI di Firebase ti verrà chiesto di abilitare le autorizzazioni per connettere i due prodotti.
Puoi disabilitare la funzione rimuovendo un ruolo IAM, come descritto in Gestisci e distribuisci le regole di sicurezza di Firebase .
Convalidare i dati
Le regole di sicurezza di Firebase per Cloud Storage possono essere utilizzate anche per la convalida dei dati, inclusa la convalida del nome e del percorso del file, nonché delle proprietà dei metadati del file come contentType
e size
.
service firebase.storage { match /b/{bucket}/o { match /images/{imageId} { // Only allow uploads of any image file that's less than 5MB allow write: if request.resource.size < 5 * 1024 * 1024 && request.resource.contentType.matches('image/.*'); } } }
Funzioni personalizzate
Man mano che le tue regole di sicurezza Firebase diventano più complesse, potresti voler racchiudere insiemi di condizioni in funzioni che puoi riutilizzare nel tuo set di regole. Le regole di sicurezza supportano funzioni personalizzate. La sintassi per le funzioni personalizzate è un po' come JavaScript, ma le funzioni Firebase Security Rules sono scritte in un linguaggio specifico del dominio che presenta alcune importanti limitazioni:
- Le funzioni possono contenere solo una singola istruzione
return
. Non possono contenere alcuna logica aggiuntiva. Ad esempio, non possono eseguire loop o chiamare servizi esterni. - Le funzioni possono accedere automaticamente a funzioni e variabili dall'ambito in cui sono definite. Ad esempio, una funzione definita nell'ambito del
service firebase.storage
ha accesso alla variabileresource
e, solo per Cloud Firestore, alle funzioni integrate comeget()
edexists()
. - Le funzioni possono chiamare altre funzioni ma non possono ricorrere. La profondità totale dello stack di chiamate è limitata a 10.
- Nella versione
rules2
, le funzioni possono definire variabili utilizzando la parola chiavelet
. Le funzioni possono avere un numero qualsiasi di associazioni let, ma devono terminare con un'istruzione return.
Una funzione è definita con la parola chiave function
e accetta zero o più argomenti. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzate negli esempi precedenti in un'unica funzione:
service firebase.storage {
match /b/{bucket}/o {
// True if the user is signed in or the requested data is 'public'
function signedInOrPublic() {
return request.auth.uid != null || resource.data.visibility == 'public';
}
match /images/{imageId} {
allow read, write: if signedInOrPublic();
}
match /mp3s/{mp3Ids} {
allow read: if signedInOrPublic();
}
}
}
L'utilizzo delle funzioni nelle tue regole di sicurezza Firebase le rende più gestibili con l'aumentare della complessità delle tue regole.
Prossimi passi
Dopo questa discussione sulle condizioni, hai una comprensione più sofisticata delle Regole e sei pronto a:
Scopri come gestire i casi d'uso principali e apprendi il flusso di lavoro per lo sviluppo, il test e l'implementazione delle regole:
- Scrivere regole che affrontino scenari comuni .
- Sviluppa le tue conoscenze rivedendo le situazioni in cui devi individuare ed evitare Regole insicure .
- Testare le regole utilizzando l' emulatore Cloud Storage e la libreria di test delle regole di sicurezza dedicata .
- Esaminare i metodi disponibili per la distribuzione delle regole .