Questa guida si basa sulla guida Sintassi di base del linguaggio delle Firebase Security Rules regole di sicurezza di Firebase per mostrare come aggiungere condizioni alle Firebase Security Rules regole di sicurezza per Cloud Storage.
Il componente di base 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 Firebase Security Rules per Cloud Storage
linguaggio ti offre modi per scrivere condizioni più complesse che possono:
- Controllare l'autenticazione dell'utente
- Convalidare i dati in entrata
Autenticazione
Firebase Security Rules per Cloud Storage si integra con Firebase Authentication per fornire una potente autenticazione basata sull'utente a Cloud Storage. Ciò consente un controllo dell'accesso granulare basato sulle attestazioni di un Firebase Authentication token.
Quando un utente autenticato esegue una richiesta a Cloud Storage,
la variabile request.auth viene compilata con l'uid dell'utente
(request.auth.uid) e con le attestazioni del JWT Firebase Authentication
(request.auth.token).
Inoltre, quando si utilizza l'autenticazione personalizzata, nel campo request.auth.token vengono visualizzate attestazioni aggiuntive.
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: controlla che
request.authnon sianull - Privato utente: controlla che
request.auth.uidsia uguale a unuiddel percorso - Privato gruppo: controlla le attestazioni del token personalizzato in modo che corrispondano a un'attestazione scelta oppure leggi i metadati del file per verificare 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 mostrare dati pubblici come asset 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 voler che i dati siano visibili a tutti gli utenti autenticati della tua applicazione, ma non agli utenti non autenticati. Poiché la variabile request.auth è null per tutti gli utenti non autenticati, non devi fare altro che 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; }
Privato utente
Il caso d'uso più comune per request.auth è di gran lunga quello di fornire ai singoli utenti autorizzazioni granulari sui propri file: dal caricamento delle foto del profilo alla lettura di documenti privati.
Poiché i file in Cloud Storage hanno un "percorso" completo, per rendere un file controllato da un utente è sufficiente un'informazione univoca che identifichi l'utente nel prefisso del nome file (ad esempio l'uid) 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; }
Privato gruppo
Un altro caso d'uso altrettanto comune è quello di consentire le autorizzazioni di gruppo su un oggetto, ad esempio consentendo a più membri del team di collaborare a un documento condiviso. Esistono diversi approcci per farlo:
- Esegui il minting di un Firebase Authentication token personalizzato che contenga informazioni aggiuntive su un membro del gruppo (ad esempio un ID gruppo)
- Includi informazioni sul gruppo (ad esempio un ID gruppo o un elenco di
uidautorizzati) in the metadati del file
Una volta che questi dati sono archiviati nel token o nei metadati del file, è possibile farvi riferimento da 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; }
Valutazione della richiesta
I caricamenti, i download, le modifiche dei metadati e le eliminazioni vengono valutati utilizzando i
request inviati 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,
l'ora in cui viene ricevuta la richiesta e il nuovo valore resource
se la richiesta è una scrittura.
L'request oggetto contiene anche l'ID univoco dell'utente e il
Firebase Authentication payload nell'request.auth oggetto, che verrà
spiegato ulteriormente nella sezione Sicurezza basata sull'utente
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 delle attestazioni JWT Firebase Authentication. In caso contrario, sarà
null. |
params |
map<string, string> | Mappa contenente i parametri di query della richiesta. |
path |
path | 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, potresti anche voler valutare 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 dimensione.
Firebase Security Rules per Cloud Storage fornisce i metadati dei file nell'resource
oggetto, che contiene coppie chiave/valore dei metadati visualizzati in un
Cloud Storage oggetto. Queste proprietà possono essere esaminate nelle richieste read o write per garantire l'integrità dei dati.
Nelle richieste write (come caricamenti, aggiornamenti dei metadati ed eliminazioni), in
aggiunta all'oggetto resource, che contiene i metadati del 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. Puoi utilizzare questi due valori per garantire l'integrità dei dati o applicare vincoli dell'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 dell'oggetto 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 in cui è stato creato 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 contiene tutte queste proprietà, ad eccezione di generation, metageneration, etag, timeCreated e updated.
Miglioramento 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 entrata rispetto ai documenti in Cloud Firestore.
Le funzioni firestore.get() e firestore.exists() prevedono entrambe percorsi di documenti completamente specificati. Quando utilizzi le variabili per creare i percorsi per firestore.get() e firestore.exists(), devi eseguire l'escape esplicito delle variabili utilizzando la sintassi $(variable).
Nell'esempio seguente, vediamo una regola che limita l'accesso in lettura ai file agli utenti che sono membri 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)).data.memberships
}
}
}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 le prime Cloud Storage Security Rules che utilizzano queste Cloud Firestore funzioni, ti verrà chiesto nella console Firebase o nell'interfaccia a riga di comando Firebase di abilitare le autorizzazioni per connettere i due prodotti.
Puoi disattivare la funzionalità rimuovendo un ruolo IAM, come descritto in Gestire ed eseguire il deployment Firebase Security Rules.
Convalida dei dati
Firebase Security Rules 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 i tuoi Firebase Security Rules diventano più complessi, potresti voler racchiudere insiemi di condizioni in funzioni che puoi riutilizzare nel tuo insieme di regole. Le regole di sicurezza supportano le funzioni personalizzate. La sintassi delle funzioni personalizzate è simile a JavaScript, ma Firebase Security Rules funzioni sono scritte in un linguaggio specifico del dominio che presenta alcune limitazioni importanti:
- Le funzioni possono contenere una sola istruzione
return. Non possono contenere 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
service firebase.storageha accesso allaresourcevariabile e, solo per Cloud Firestore, alle funzioni integrate comeget()eexists(). - Le funzioni possono chiamare altre funzioni, ma non possono essere ricorsive. La profondità totale dello stack di chiamate è limitata a 10.
- Nella versione
rules2, le funzioni possono definire le variabili utilizzando la parola chiavelet. Le funzioni possono avere un numero qualsiasi di binding let, ma devono terminare con un'istruzione return.
Una funzione viene definita con la parola chiave function e accetta zero o più argomenti. Ad esempio, potresti voler combinare i due tipi di condizioni utilizzati negli esempi precedenti in una singola 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 Firebase Security Rules le rende più gestibili man mano che la complessità delle regole aumenta.
Passaggi successivi
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 il flusso di lavoro per lo sviluppo, il test e il deployment delle regole:
- Scrivi regole che riguardano scenari comuni.
- Amplia le tue conoscenze esaminando le situazioni in cui devi individuare ed evitare regole non sicure.
- Testa le regole utilizzando l'Cloud Storage emulatore e la libreria di test delle regole di sicurezza dedicata.
- Esamina i metodi disponibili per il deployment Security Rules.