Questa guida si basa sulla guida Impara la sintassi di base del linguaggio Firebase Security Rules per mostrare come aggiungere condizioni a Firebase Security Rules per Cloud Storage.
L'elemento costitutivo principale di Cloud Storage Security Rules è la condizione. Una condizione è un'espressione booleana che determina se una determinata operazione deve essere consentita o negata. Per le regole di base, l'utilizzo di valori letterali true
e false
come condizioni funziona perfettamente. Tuttavia, il linguaggio Firebase Security Rules per Cloud Storage
offre modi per scrivere condizioni più complesse che possono:
- Controllare l'autenticazione utente
- Convalida i dati in entrata
Autenticazione
Firebase Security Rules per Cloud Storage si integra con Firebase Authentication per fornire una potente autenticazione basata sugli utenti a Cloud Storage. Ciò consente un controllo granulare dell'accesso in base alle rivendicazioni di un token Firebase Authentication.
Quando un utente autenticato esegue una richiesta a Cloud Storage,
la variabile request.auth
viene compilata con il uid
dell'utente (request.auth.uid
) e con le attestazioni del JWT Firebase Authentication
(request.auth.token
).
Inoltre, quando utilizzi l'autenticazione personalizzata, nel campo request.auth.token
vengono visualizzati altri claim.
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
- Privato utente: verifica che
request.auth.uid
sia uguale a un percorsouid
- Gruppo privato: controlla le rivendicazioni del token personalizzato per trovare una rivendicazione scelta o leggi i metadati del file per verificare se esiste un campo dei metadati
Pubblico
Qualsiasi regola che non tenga conto del contesto request.auth
può essere considerata una regola public
, poiché non tiene conto del contesto di autenticazione dell'utente.
Queste regole possono essere utili per mostrare dati pubblici come asset di giochi, 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, devi solo verificare 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; }
Privato dell'utente
Il caso d'uso più comune di request.auth
sarà fornire ai singoli utenti autorizzazioni granulari sui loro file: dal caricamento delle foto del profilo alla lettura di documenti privati.
Poiché i file in Cloud Storage hanno un "percorso" completo, per fare in modo che un file sia controllato da un utente è sufficiente un'informazione univoca che identifichi l'utente nel prefisso del nome file (ad esempio il uid
dell'utente) che può essere controllata quando viene valutata la regola:
// 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 è consentire le autorizzazioni di gruppo per un oggetto, ad esempio consentire a più membri del team di collaborare a un documento condiviso. Esistono diversi approcci per farlo:
- Crea un Firebase Authentication token personalizzato che contiene informazioni aggiuntive su un membro del gruppo (ad esempio un ID gruppo)
- Includi le informazioni sul gruppo (ad esempio un ID gruppo o un elenco di
uid
autorizzati) nei metadati del file
Una volta archiviati nei metadati del token o del file, a questi dati è possibile fare 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
I caricamenti, i download, le modifiche e le eliminazioni dei metadati vengono valutati utilizzando il
request
inviato a Cloud Storage. Oltre all'ID univoco dell'utente e al payload Firebase Authentication nell'oggetto request.auth
come descritto sopra, la variabile request
contiene il percorso del file in cui viene eseguita la richiesta, la data e l'ora di ricezione della richiesta e il nuovo valore resource
se la richiesta è di scrittura.
L'oggetto request
contiene anche l'ID univoco dell'utente e il payload Firebase Authentication nell'oggetto request.auth
, che verrà spiegato ulteriormente nella sezione Sicurezza basata sugli utenti della documentazione.
Di seguito è riportato un elenco completo delle proprietà dell'oggetto request
:
Proprietà | Tipo | Descrizione |
---|---|---|
auth |
map<string, string> | Quando un utente ha eseguito l'accesso, fornisce uid , l'ID univoco dell'utente, e
token , una mappa di attestazioni JWT Firebase Authentication. In caso contrario, sarà
null . |
params |
map<string, string> | Mappa contenente i parametri di query della richiesta. |
path |
percorso | Un path che rappresenta il percorso in cui viene eseguita la richiesta. |
resource |
map<string, string> | 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 valuti le regole, ti consigliamo di valutare anche i metadati del file caricato, scaricato, modificato o eliminato. In questo modo, puoi creare regole complesse e potenti che, ad esempio, consentono di caricare solo file con determinati tipi di contenuti o di eliminare solo file di dimensioni superiori a una determinata.
Firebase Security Rules per Cloud Storage fornisce i metadati del file nell'oggetto resource
, che contiene coppie chiave/valore dei metadati visualizzati in un oggetto Cloud Storage. Queste proprietà possono essere controllate nelle richieste read
o
write
per garantire l'integrità dei dati.
Nelle richieste write
(come caricamenti, aggiornamenti dei metadati ed eliminazioni), oltre all'oggetto resource
, che contiene i metadati del file attualmente esistente nel percorso della richiesta, puoi anche utilizzare l'oggetto request.resource
, che contiene un sottoinsieme dei metadati del file da scrivere se la scrittura è consentita. Puoi utilizzare questi due valori per garantire l'integrità dei dati o applicare vincoli di applicazione come il tipo o le dimensioni del file.
Di seguito è riportato un elenco completo delle proprietà dell'oggetto resource
:
Proprietà | Tipo | Descrizione |
---|---|---|
name |
stringa | Il nome completo dell'oggetto |
bucket |
stringa | Il nome del bucket in cui si trova questo oggetto. |
generation |
int | La Google Cloud Storage generazione di oggetti di questo oggetto. |
metageneration |
int | La Google Cloud Storage metagenerazione dell'oggetto di questo oggetto. |
size |
int | Le dimensioni dell'oggetto in byte. |
timeCreated |
timestamp | Un timestamp che rappresenta l'ora di creazione di un oggetto. |
updated |
timestamp | Un timestamp che rappresenta l'ora dell'ultimo aggiornamento di un oggetto. |
md5Hash |
stringa | Un hash MD5 dell'oggetto. |
crc32c |
stringa | Un hash crc32c dell'oggetto. |
etag |
stringa | L'etag associato a questo oggetto. |
contentDisposition |
stringa | La disposizione dei contenuti associata a questo oggetto. |
contentEncoding |
stringa | La codifica dei contenuti associata a questo oggetto. |
contentLanguage |
stringa | La lingua dei contenuti associata a questo oggetto. |
contentType |
stringa | Il tipo di contenuti associato a questo oggetto. |
metadata |
map<string, string> | Coppie chiave/valore di metadati personalizzati aggiuntivi specificati dallo sviluppatore. |
request.resource
li contiene tutti, 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 regole di sicurezza possono valutare le richieste in arrivo in base ai documenti in Cloud Firestore.
Entrambe le funzioni firestore.get()
e firestore.exists()
prevedono percorsi dei documenti completamente specificati. Quando utilizzi le variabili per creare percorsi per firestore.get()
e firestore.exists()
, devi eseguire esplicitamente l'escapismo delle variabili utilizzando la sintassi $(variable)
.
Nell'esempio seguente viene mostrata una regola che limita l'accesso in lettura ai file agli utenti che fanno parte di determinati club.
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 } } }Nell'esempio seguente, solo gli amici di un utente possono vedere le sue 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)) } } }
Dopo aver creato e salvato il primo Cloud Storage Security Rules che utilizza queste funzioni Cloud Firestore, nella console Firebase o nell'interfaccia a riga di comando Firebase ti verrà chiesto di attivare le autorizzazioni per collegare i due prodotti.
Puoi disattivare la funzionalità rimuovendo un ruolo IAM, come descritto in Gestisci ed esegui il deployment di Firebase Security Rules.
Convalida dei dati
Firebase Security Rules per Cloud Storage può essere utilizzato 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 Firebase Security Rules diventa più complesso, ti consigliamo di racchiudere insiemi di condizioni in funzioni che puoi riutilizzare nel set di regole. Le regole di sicurezza supportano le funzioni personalizzate. La sintassi delle funzioni personalizzate è un po' simile a quella di JavaScript, ma le funzioni Firebase Security Rules sono scritte in un linguaggio specifico per dominio con alcune limitazioni importanti:
- Le funzioni possono contenere una sola istruzione
return
. Non possono contenere alcuna logica aggiuntiva. Ad esempio, non possono eseguire loop o chiamare servizi esterni. - Le funzioni possono accedere automaticamente alle funzioni e alle variabili dall'ambito
in cui sono definite. Ad esempio, una funzione definita all'interno
dell'ambito
service firebase.storage
ha accesso alla variabileresource
e, solo per Cloud Firestore, alle funzioni predefinite comeget()
eexists()
. - Le funzioni possono chiamare altre funzioni, ma non possono essere ricorsive. La profondità totale della pila 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 utilizzati
gli 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 di funzioni in Firebase Security Rules le rende più gestibili man mano che la complessità delle regole aumenta.
Passaggi successivi
Dopo questa discussione sulle condizioni, hai una conoscenza più approfondita delle Regole e puoi:
Scopri come gestire i casi d'uso principali e il flusso di lavoro per lo sviluppo, la verifica e il deployment delle regole:
- Scrivi regole che rispondano a scenari comuni.
- Amplia le tue conoscenze esaminando le situazioni in cui devi individuare ed evitare regole non sicure.
- Testa le regole utilizzando l'emulatore Cloud Storage e la libreria di test delle regole di sicurezza dedicata.
- Esamina i metodi disponibili per il deployment di Rules.