Quando si sviluppa un'applicazione iOS nativa che utilizza Cloud Firestore come database NoSQL serverless, la sicurezza dei dati non risiede sul dispositivo client, ma è affidata interamente alle Firestore Security Rules. Lasciare le regole in modalità di test o utilizzare verifiche generiche (come allow read, write: if request.auth != null;) espone l'applicazione a rischi gravissimi di sottrazione o alterazione dei dati.
1. Il Principio del Minimo Privilegio
Le Security Rules di Firestore funzionano su base deny-by-default: se nessuna regola autorizza esplicitamente un'operazione, la richiesta viene bloccata. È fondamentale separare i permessi di lettura in get (lettura singolo documento) e list (query su collezioni), e i permessi di scrittura in create, update e delete.
Esempio Pratico di Security Rules Produzione
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// Helper functions
function isAuthenticated() {
return request.auth != null;
}
function isOwner(userId) {
return isAuthenticated() && request.auth.uid == userId;
}
function hasRole(role) {
return isAuthenticated() && request.auth.token.role == role;
}
// Regole per la collezione degli utenti
match /users/{userId} {
allow get: if isAuthenticated();
allow list: if hasRole('admin');
allow create: if isOwner(userId)
&& request.resource.data.keys().hasAll(['email', 'createdAt'])
&& request.resource.data.email is string;
allow update: if isOwner(userId)
&& !request.resource.data.diff(resource.data).affectedKeys().hasAny(['role', 'createdAt']);
allow delete: if hasRole('admin');
}
// Regole per post e contenuti
match /posts/{postId} {
allow read: if true; // Pubblico in lettura
allow create: if isAuthenticated()
&& request.resource.data.authorId == request.auth.uid
&& request.resource.data.title.size() >= 3;
allow update, delete: if isAuthenticated()
&& resource.data.authorId == request.auth.uid;
}
}
}
2. Integrazione nel Client iOS (SwiftUI & Swift)
Lato client in SwiftUI, è necessario intercettare e gestire gli errori di permesso negato generati da Firebase per mostrare messaggi chiari all'utente o eseguire il rollback dello stato locale.
import SwiftUI
import FirebaseFirestore
import FirebaseAuth
final class PostViewModel: ObservableObject {
@Published var posts: [Post] = []
@Published var errorMessage: String?
private let db = Firestore.firestore()
func createPost(title: String, content: String) {
guard let currentUid = Auth.auth().currentUser?.uid else {
self.errorMessage = "Utente non autenticato."
return
}
let newPost: [String: Any] = [
"title": title,
"content": content,
"authorId": currentUid,
"createdAt": FieldValue.serverTimestamp()
]
db.collection("posts").addDocument(data: newPost) { error in
if let error = error as NSError? {
if error.code == FirestoreErrorCode.permissionDenied.rawValue {
self.errorMessage = "Non disponi dei permessi per pubblicare questo post."
} else {
self.errorMessage = error.localizedDescription
}
}
}
}
}
Conclusioni
Implementare le Firestore Security Rules con validazione dello schema e verifica dei token garantisce che il tuo database sia corazzato contro qualsiasi abuso. Per consulenze architetturali su Firebase ed iOS, contatta Yunus Diallo (DialloDev) a diallooyunus@gmail.com.