Cloud Firestore Güvenlik Kuralları için yazma koşulları

Bu kılavuzda, Cloud Firestore Security Rules öğenize nasıl koşul ekleyeceğiniz gösterilmektedir. Bu bilgiler, güvenlik kurallarını yapılandırma kılavuzundan alınmıştır. Cloud Firestore Security Rules'ün temel özelliklerini bilmiyorsanız başlangıç kılavuzuna göz atın.

Cloud Firestore Security Rules işlevinin birincil yapı taşı koşuldur. Koşul, belirli bir işleme izin verilip verilmeyeceğini belirleyen bir boole ifadesidir. Kullanıcı kimlik doğrulamasını kontrol eden, gelen verileri doğrulayan veya hatta veritabanınızın diğer bölümlerine erişen koşullar yazmak için güvenlik kurallarını kullanın.

Doğrulama

En yaygın güvenlik kuralı kalıplarından biri, erişimi kullanıcının kimlik doğrulama durumuna göre kontrol etmektir. Örneğin, uygulamanız yalnızca oturum açmış kullanıcıların veri yazmasına izin vermek isteyebilir:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to access documents in the "cities" collection
    // only if they are authenticated.
    match /cities/{city} {
      allow read, write: if request.auth != null;
    }
  }
}

Yaygın bir başka model de kullanıcıların yalnızca kendi verilerini okuyup yazabilmesini sağlamaktır:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure the uid of the requesting user matches name of the user
    // document. The wildcard expression {userId} makes the userId variable
    // available in rules.
    match /users/{userId} {
      allow read, update, delete: if request.auth != null && request.auth.uid == userId;
      allow create: if request.auth != null;
    }
  }
}

Uygulamanız Firebase Authentication veya Google Cloud Identity Platform kullanıyorsa request.auth değişkeni, veri isteyen istemcinin kimlik doğrulama bilgilerini içerir. request.auth hakkında daha fazla bilgi için referans dokümanlarına bakın.

Veri doğrulama

Birçok uygulama, erişim denetimi bilgilerini veritabanındaki dokümanlarda alan olarak depolar. Cloud Firestore Security Rules, doküman verilerine göre erişime dinamik olarak izin verebilir veya erişimi reddedebilir:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

resource değişkeni istenen dokümanı, resource.data ise dokümanda depolanan tüm alanların ve değerlerin haritasını ifade eder. resource değişkeni hakkında daha fazla bilgi için referans belgelerine bakın.

Veri yazarken gelen verileri mevcut verilerle karşılaştırmak isteyebilirsiniz. Bu durumda, kural kümeniz bekleyen yazma işlemine izin veriyorsa request.resource değişkeni, belgenin gelecekteki durumunu içerir. Yalnızca belge alanlarının bir alt kümesini değiştiren update işlemleri için request.resource değişkeni, işlemden sonra bekleyen belge durumunu içerir. İstenmeyen veya tutarsız veri güncellemelerini önlemek için request.resource alanındaki alan değerlerini kontrol edebilirsiniz:

service cloud.firestore {
  match /databases/{database}/documents {
    // Make sure all cities have a positive population and
    // the name is not changed
    match /cities/{city} {
      allow update: if request.resource.data.population > 0
                    && request.resource.data.name == resource.data.name;
    }
  }
}

Diğer dokümanlara erişme

Güvenlik kurallarınızda get() ve exists() işlevlerini kullanarak gelen istekleri veritabanındaki diğer belgelerle karşılaştırabilirsiniz. Hem get() hem de exists() işlevleri, tamamen belirtilen belge yolları bekler. get() ve exists() için yollar oluşturmak amacıyla değişkenler kullanırken $(variable) söz dizimini kullanarak değişkenleri açıkça kaçış karakteri eklemeniz gerekir.

Aşağıdaki örnekte, database değişkeni eşleme ifadesi match /databases/{database}/documents tarafından yakalanır ve yolu oluşturmak için kullanılır:

service cloud.firestore {
  match /databases/{database}/documents {
    match /cities/{city} {
      // Make sure a 'users' document exists for the requesting user before
      // allowing any writes to the 'cities' collection
      allow create: if request.auth != null && exists(/databases/$(database)/documents/users/$(request.auth.uid));

      // Allow the user to delete cities if their user document has the
      // 'admin' field set to 'true'
      allow delete: if request.auth != null && get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    }
  }
}

Yazma işlemleri için, bir işlem veya yazma grubu tamamlandıktan sonra ancak işlem veya grup taahhüt edilmeden önce bir belgenin durumuna erişmek üzere getAfter() işlevini kullanabilirsiniz. get() işlevi gibi getAfter() işlevi de tam olarak belirtilen bir belge yolu alır. Bir işlem veya toplu işlem olarak birlikte yapılması gereken yazma gruplarını tanımlamak için getAfter() kullanabilirsiniz.

Arama sınırlarına erişim

Kural grubu değerlendirmesi başına belge erişimi çağrıları için bir sınır vardır:

  • Tek belgeli istekler ve sorgu istekleri için 10.
  • Çok belgeli okumalar, işlemler ve toplu yazmalar için 20. Her işlemde yukarıdaki 10 sınırı da geçerlidir.

    Örneğin, 3 yazma işlemiyle bir toplu yazma isteği oluşturduğunuzu ve güvenlik kurallarınızın her yazma işlemini doğrulamak için 2 belge erişimi çağrısı kullandığını varsayalım. Bu durumda her yazma işlemi 10 erişim çağrısından 2'sini; toplu yazma isteği ise 20 erişim çağrısından 6'sını kullanır.

Her iki sınırın da aşılması, "izin verilmedi" hatasıyla sonuçlanır. Bazı belge erişimi çağrıları önbelleğe alınabilir. Önbelleğe alınan çağrılar sınırlamaya dahil edilmez.

Bu sınırların işlemleri ve toplu yazma işlemlerini nasıl etkilediğiyle ilgili ayrıntılı bir açıklama için atomik işlemlerin güvenliğini sağlama başlıklı kılavuzu inceleyin.

Aramalara ve fiyatlandırmaya erişme

Bu işlevler kullanıldığında veritabanınızda bir okuma işlemi gerçekleştirilir. Bu, kurallarınız isteği reddetse bile belgeler için okuma ücreti ödeyeceğiniz anlamına gelir. Daha ayrıntılı faturalandırma bilgileri için Cloud Firestore Fiyatlandırma başlıklı makaleyi inceleyin.

Özel işlevler

Güvenlik kurallarınız daha karmaşık hale geldikçe, koşul gruplarını kural kümenizde yeniden kullanabileceğiniz işlevlere sarmalamak isteyebilirsiniz. Güvenlik kuralları özel işlevleri destekler. Özel işlevlerin söz dizimi JavaScript'e biraz benzer ancak güvenlik kuralları işlevleri, bazı önemli sınırlamaları olan alana özgü bir dilde yazılır:

  • İşlevler yalnızca tek bir return ifadesi içerebilir. Bu işlevler ek mantık içeremez. Örneğin, döngü yürütemez veya harici hizmetleri çağıramaz.
  • İşlevler, tanımlandıkları kapsamdaki işlevlere ve değişkenlere otomatik olarak erişebilir. Örneğin, service cloud.firestore kapsamında tanımlanan bir işlev, resource değişkenine ve get() ile exists() gibi yerleşik işlevlere erişebilir.
  • İşlevler diğer işlevleri çağırabilir ancak yineleme yapamaz. Toplam çağrı yığını derinliği 10 ile sınırlıdır.
  • v2 kuralları sürümünde işlevler, let anahtar kelimesini kullanarak değişkenler tanımlayabilir. İşlevler en fazla 10 let bağlaması içerebilir ancak return ifadesiyle bitmelidir.

İşlevler function anahtar kelimesiyle tanımlanır ve sıfır veya daha fazla bağımsız değişken alır. Örneğin, yukarıdaki örneklerde kullanılan iki koşul türünü tek bir işlevde birleştirmek isteyebilirsiniz:

service cloud.firestore {
  match /databases/{database}/documents {
    // 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 /cities/{city} {
      allow read, write: if signedInOrPublic();
    }

    match /users/{user} {
      allow read, write: if signedInOrPublic();
    }
  }
}

Güvenlik kurallarınızda işlevler kullanmak, kurallarınızın karmaşıklığı arttıkça bu kuralları daha kolay yönetilebilir hale getirir.

Kurallar filtre değildir

Verilerinizin güvenliğini sağladıktan ve sorgu yazmaya başladıktan sonra güvenlik kurallarının filtre olmadığını unutmayın. Bir koleksiyondaki tüm dokümanlar için sorgu yazarken Cloud Firestore'ün yalnızca mevcut istemcinin erişmesine izin verilen dokümanları döndürmesini bekleyemezsiniz.

Örneğin, aşağıdaki güvenlik kuralını ele alalım:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow the user to read data if the document has the 'visibility'
    // field set to 'public'
    match /cities/{city} {
      allow read: if resource.data.visibility == 'public';
    }
  }
}

Reddedildi: Sonuç kümesi, visibility değerinin public olmadığı dokümanları içerebileceği için bu kural aşağıdaki sorguyu reddeder:

Web
db.collection("cities").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
    });
});

İzin veriliyor: where("visibility", "==", "public") yan tümcesi, sonuç kümesinin kuralın koşulunu karşıladığını garanti ettiği için bu kural aşağıdaki sorguya izin verir:

Web
db.collection("cities").where("visibility", "==", "public").get()
    .then(function(querySnapshot) {
        querySnapshot.forEach(function(doc) {
            console.log(doc.id, " => ", doc.data());
        });
    });

Cloud Firestore güvenlik kuralları her sorguyu olası sonucuna göre değerlendirir ve istemcinin okuma izni olmayan bir doküman döndürebileceği durumlarda isteği reddeder. Sorgular, güvenlik kurallarınız tarafından belirlenen kısıtlamalara uymalıdır. Güvenlik kuralları ve sorgular hakkında daha fazla bilgi için verileri güvenli bir şekilde sorgulama başlıklı makaleyi inceleyin.

Sonraki adımlar