Klasik API isteği yapma

Yalnızca standart API taleplerin çoğu için uygun olduğunu geliştirirken, Google Haritalar'da bütünlük ekleyebilirsiniz. Bu sayfada, klasik oluşturma Android 4.4 (API) sürümünde desteklenen entegrasyon kararları için API istekleri 19. seviye) veya daha üst bir seviyedir.

Dikkat edilmesi gereken noktalar

Standart ve klasik istekleri karşılaştırma

Standart istekler, klasik istekler veya bu ikisinin bir kombinasyonunu gönderebilirsiniz Bu da uygulamanızın güvenliğine ve kötüye kullanımı önleme ihtiyaçlarına bağlıdır. Standart istekler Tüm uygulamalar ve oyunlar için uygundur ve herhangi bir işlem veya sunucu çağrısı orijinaldir, ancak tekrar oynanabilirliğe karşı koruma yetkilendirmesi içerir Google Play'deki veri hırsızlığını yapıyor. Klasik isteklerin gönderilmesi daha pahalıdır ve karşı koruma sağlamak için bu uyarıları doğru şekilde uygulamak ve belirli saldırı türlerini kapsar. Klasik istekler daha az yapılmalıdır standart isteklerden daha sık aralıklarla (örneğin, kontrol etmek için ara sıra yapılan tek seferlik istekler) çok değerli veya hassas bir işlem gerçekse.

Aşağıdaki tabloda, iki farklı kampanya türü arasındaki temel farklar açıklanmaktadır. istekler:

Standart API isteği Klasik API isteği
Ön koşullar
Minimum Android SDK sürümü gerekli Android 5.0 (API düzeyi 21) veya sonraki sürümler Android 4.4 (API düzeyi 19) veya sonraki sürümler
Google Play şartları Google Play Store ve Google Play Hizmetleri Google Play Store ve Google Play Hizmetleri
Entegrasyon ayrıntıları
API ısınma gerekli ✔️ (birkaç saniye)
Normal istek gecikmesi Birkaç yüz milisaniye Birkaç saniye
Olası istek sıklığı Sık (herhangi bir işlem veya istek için talep üzerine kontrol) Nadir (en yüksek değere sahip işlemler veya en hassas istekler için tek seferlik kontrol)
Engelleme Çoğu ısınma süresi 10 saniyeden kısadır ancak bir sunucu çağrısı içerdiğinden uzun bir zaman aşımı süresi (ör. 1 dakika) önerilir. Karar istekleri istemci tarafında gerçekleşir Çoğu istek 10 saniyeden kısa sürer ancak bir sunucu çağrısı içerdiğinden uzun bir zaman aşımı süresi önerilir (ör. 1 dakika)
Integrity karar jetonu
Cihaz, uygulama ve hesap ayrıntılarını içerir
Jeton önbelleğe alma Google Play tarafından korunan cihaz üzerinde önbelleğe alma Önerilmez
Google Play sunucusu üzerinden jetonun şifresini çözün ve doğrulayın
Tipik şifre çözme sunucudan sunucuya istek gecikmesi 10 sn. (üç dokuz kullanılabilirlik) 10 sn. (üç dokuz kullanılabilirlik)
Güvenli bir sunucu ortamında jetonun şifresini çözün ve yerel olarak jetonu doğrulayın
Jeton istemci tarafında şifre çözme ve jetonu doğrulama
Entegrasyon kararının güncelliği Google Play tarafından sunulan bazı otomatik önbelleğe alma ve yenileme işlemleri Tüm kararlar her istek için yeniden hesaplandı
Sınırlar
Uygulama başına günlük istek sayısı Varsayılan olarak 10.000 (artış istenebilir) Varsayılan olarak 10.000 (artış istenebilir)
Dakikada uygulama örneği başına istek sayısı Isınma: Dakikada 5
Bütünlük jetonları: Herkese açık sınır yok*
Bütünlük jetonları: Dakikada 5
Koruma
İzinsiz değişiklik ve benzer saldırılara karşı azaltın requestHash alanını kullan nonce alanını istek verilerine göre içerik bağlamayla kullanın
Tekrar oynatma ve benzer saldırılara karşı azaltın Google Play'den otomatik çözüm nonce alanını sunucu tarafı mantığıyla kullan

* Herkese açık sınırları olmayanlar dahil tüm istekler, kamu dışı yüksek değerlerdeki savunma sınırlarına tabidir

Nadiren klasik istekler gönderme

Bütünlük jetonu oluşturma işleminde zaman, veri ve pil kullanılır ve her uygulamanın bir günlük maksimum klasik istek sayısı. Bu nedenle yalnızca en yüksek değeri veya en hassas işlemleri kontrol etmek için klasik isteklerde bulun standart bir isteğe ek garanti istediğinizde orijinaldir. Siz yüksek sıklığa sahip veya düşük değerli işlemler için klasik istekler yapmamalıdır. Şunları Yapmayın: uygulama her ön plana gittiğinde veya birkaç haftada bir klasik istek göndermek kullanın ve çok sayıda cihazdan arama yapmaktan kaçının. anlamına gelir. Çok fazla klasik istek çağrısı yapan bir uygulama, ve kullanıcıları yanlış uygulamalara karşı koruyabilir.

Sonuçları önbelleğe almaktan kaçınma

Bir kararı önbelleğe almak, hırsızlık ve tekrar oynatma gibi saldırı riskini artırır. güvenilir olmayan bir ortamdan iyi bir karar tekrar kullanıldığında. Eğer klasik bir istek oluşturmayı ve daha sonra kullanmak üzere önbelleğe almayı düşünürseniz isteğe bağlı standart bir istek gerçekleştirmek için önerilir. Standart istekler cihazda önbelleğe alma işlemi yapılmasını içerir, ancak Google Play ek koruma kullanır saldırı ve veri hırsızlığı riskini azaltmaya yönelik teknikler bulunmaktadır.

Klasik istekleri korumak için tek seferlik rastgele sayı alanını kullanma

Play Integrity API, kullanabileceğiniz nonce adlı bir alanı sunar. Uygulamanızı tekrar oynatma ve izinsiz değişiklik gibi belirli saldırılara karşı daha iyi koruma anlamına gelir. Play Integrity API, bu alanda ayarladığınız değeri imzalanması gerekir. Nasıl oluşturacağınıza ilişkin nonce ile uygulamanızı saldırılardan koruyun.

Klasik istekleri eksponansiyel geri yükleme ile yeniden dene

Kararsız İnternet bağlantısı veya cihaz bütünlüğü kontrollerinin başarısız olmasına neden olabilir. Bu da güvenilir olan bir cihaz için etiket oluşturulmadığından emin olun. Alıcı: eksponansiyel geri yükleme ile bir yeniden deneme seçeneği sunun.

Genel Bakış

Play Integrity'nin üst düzey tasarımını gösteren sıra şeması
API

Kullanıcı, uygulamanızda korumak istediğiniz yüksek değerli bir işlem gerçekleştirdiğinde aşağıdaki adımları tamamlayın:

  1. Uygulamanızın sunucu tarafı arka ucu, benzersiz bir değer oluşturur ve mantığıyla çalışır. Geri kalan adımlarda bu mantık "uygulamanız" olarak adlandırılır.
  2. Uygulamanız, uygulamanızın benzersiz değerinden ve içeriğinden nonce oluşturur yüksek değerli bir eylemdir. Daha sonra Play Integrity API'yi çağırarak nonce
  3. Uygulamanız, Play Integrity'den imzalı ve şifrelenmiş bir karar alır API'ye gidin.
  4. Uygulamanız, imzalı ve şifrelenmiş kararı uygulamanızın arka ucuna iletir.
  5. Uygulamanızın arka ucu, kararı bir Google Play sunucusuna gönderir. Google Play sunucusu kararın şifresini çözüp kararı doğrular ve sonuçları cihazınıza döndürür. arka ucudur.
  6. Uygulamanızın arka ucu, belirtiliyor.
  7. Uygulamanızın arka ucu, karar sonuçlarını uygulamanıza gönderir.

Tek seferlik rastgele sayı oluştur

Uygulamanızdaki bir işlemi Play Integrity API ile koruyarak şunları yapabilirsiniz: şunun gibi belirli saldırı türlerini azaltmak için nonce alanından yararlanın: ortadaki kişi (PITM) saldırısı ve tekrar eden saldırılar. Oyun Integrity API, bu alanda ayarladığınız değeri imzalı emin olun.

nonce alanında ayarlanan değer doğru şekilde biçimlendirilmelidir:

  • String
  • URL açısından güvenli
  • Base64 olarak kodlanır ve sarmalamaz
  • En az 16 karakter
  • Maksimum 500 karakter

Play'de nonce alanını kullanmanın yaygın olarak kullanılan bazı yolları aşağıda verilmiştir Integrity API'ye dokunun. nonce karşı en güçlü korumayı elde etmek için şunları birleştirebilirsiniz: aşağıdaki yöntemleri inceleyin.

İzinsiz olarak değiştirilmeye karşı koruma sağlamak için istek karması ekleyin

nonce parametresini, aşağıdakine benzer şekilde klasik bir API isteğinde kullanabilirsiniz: Bir standart API isteğinde bulunan requestHash parametresinden talep edilebilir.

Entegrasyon kararı istediğinizde:

  1. Tüm kritik istek parametrelerinin (ör. kararlı bir çalışmanın SHA256) özetini serileştirme isteği) gönderen kullanıcı işleminden veya sunucu isteğinden bahsedeceğim.
  2. nonce alanını hesaplanan özetin değerine ayarlamak için setNonce işlevini kullanın.

Entegrasyon kararı aldığınızda:

  1. Bütünlük jetonunun kodunu çözüp doğrulayın ve nonce alanı boş bırakılamaz.
  2. İsteğin özetini uygulamada olduğu gibi (ör. SHA256'yı destekler).
  3. Uygulama tarafı ve sunucu tarafı özetlerini karşılaştırın. Bunlar eşleşmezse bu istek güvenilir olmayabilir.
ziyaret edin.

Tekrarlanan saldırılara karşı korumak için benzersiz değerler ekleyin.

Kötü amaçlı kullanıcıların Play Integrity API ile her birini benzersiz şekilde tanımlamak için nonce alanını kullanabilirsiniz mesajını alırsınız.

Entegrasyon kararı istediğinizde:

  1. Kötü amaçlı kullanıcıların tahmin edemeyeceği şekilde genel olarak benzersiz bir değer elde edin. Örneğin, sunucu tarafı böyle bir değer veya bir oturum ya da işlem kimliği. Daha basit ve daha az güvenli bir varyant, rastgele bir rastgele değer telefon numarası da var. 128 bit veya daha büyük değerler oluşturmanızı öneririz.
  2. nonce alanını 1. adımdaki benzersiz değere ayarlamak için setNonce() komutunu çağırın.

Entegrasyon kararı aldığınızda:

  1. Bütünlük jetonunun kodunu çözüp doğrulayın ve nonce alanı boş bırakılamaz.
  2. 1. adımdaki değer sunucuda oluşturulduysa benzersiz değerin, oluşturulan değerlerden biri olduğunu ve bunu, ilk kez kullanılırsa (sunucunuzun, oluşturulan verilerin kaydını tutması uygun bir süre için kullanılabilir). Alınan benzersiz değer kullanılmışsa kayıtta görünüyor veya görünmüyorsa isteği reddedin
  3. Aksi takdirde, benzersiz değer cihazda oluşturulmuşsa değeri ilk kez kullanılıp kullanılmadığını (sunucunuzun uygun bir süre boyunca görülen değerlerin kaydı). Alınan benzersiz değer zaten kullanıldı, isteği reddedin.

İzinsiz değişiklik ve tekrar saldırılarına karşı iki korumayı bir arada kullanın (önerilir)

nonce alanı, hem izinsiz değişiklik hem de aynı anda tekrarlayabilir. Bunu yapmak için, benzersiz değeri ve talebinize eklemeniz gerekir. Daha sonra benzersiz değeri karmanın bir parçası olarak eklediğinizden emin olun. aşağıdaki yöntemlerin bir araya gelmesiyle oluşur:

Entegrasyon kararı istediğinizde:

  1. Yüksek değerli işlemi kullanıcı başlatır.
  2. Bu işlem için, Benzersiz dahil et: değerleri bölümünü inceleyin.
  3. Korumak istediğiniz bir mesaj hazırlayın. 2. adımdaki benzersiz değeri ekleyin sağlayabilirsiniz.
  4. Uygulamanız, korumak istediği mesajın bir özetini hesaplar. karşı koruma için istek karması ekleme konusunda bölümünü inceleyin. İleti, benzersiz tanımlayıcı benzersiz değer, karmanın bir parçasıdır.
  5. setNonce() öğesini kullanarak nonce alanını önceki adım.

Entegrasyon kararı aldığınızda:

  1. İstekten benzersiz değeri elde etme
  2. Bütünlük jetonunun kodunu çözüp doğrulayın ve nonce alanı boş bırakılamaz.
  3. İzinsiz değişikliklere karşı koruma sağlamak için istek karması ekleme konusunda açıklandığı gibi bölümünde, özeti sunucu tarafında yeniden hesaplayın ve özetin sunucu tarafında bütünlük jetonundan alınan özet bilgileridir.
  4. İçerik tekrar oynatmaya karşı koruma sağlamak için benzersiz değerler ekleme konusunda açıklandığı gibi saldırılar bölümünde, benzersiz değerin geçerliliğini kontrol edin.

Aşağıdaki sıra şemasında, bu adımlar sunucu tarafı nonce:

Hem izinsiz değişikliğe hem de tekrar oynatmaya karşı nasıl korunacağını gösteren sıra şeması
saldırılar

Entegrasyon kararı iste

nonce oluşturduktan sonra Google'dan entegrasyon kararı isteyebilirsiniz Oyna. Bunun için aşağıdaki adımları uygulayın:

  1. Aşağıdaki örneklerde gösterildiği gibi bir IntegrityManager oluşturun.
  2. Bir IntegrityTokenRequest oluşturun. nonce görevini İlişkilendirilmiş derleyicide setNonce() yöntemi. Özel olarak dağıtılan uygulamalar SDK'ların da kendi Google Cloud platformlarını proje numarasını setCloudProjectNumber() yöntemiyle arayın. Google'da Uygulamalar Play, Play Console'da bir Cloud projesine bağlıdır ve bu projenin İstekte Cloud projesi numarasını ayarlayın.
  3. Yöneticiyi kullanarak requestIntegrityToken() numaralı telefonu arayarak IntegrityTokenRequest.

Kotlin

// Receive the nonce from the secure server.
val nonce: String = ...

// Create an instance of a manager.
val integrityManager =
    IntegrityManagerFactory.create(applicationContext)

// Request the integrity token by providing a nonce.
val integrityTokenResponse: Task<IntegrityTokenResponse> =
    integrityManager.requestIntegrityToken(
        IntegrityTokenRequest.builder()
             .setNonce(nonce)
             .build())

Java

import com.google.android.gms.tasks.Task; ...

// Receive the nonce from the secure server.
String nonce = ...

// Create an instance of a manager.
IntegrityManager integrityManager =
    IntegrityManagerFactory.create(getApplicationContext());

// Request the integrity token by providing a nonce.
Task<IntegrityTokenResponse> integrityTokenResponse =
    integrityManager
        .requestIntegrityToken(
            IntegrityTokenRequest.builder().setNonce(nonce).build());

Üçlü

IEnumerator RequestIntegrityTokenCoroutine() {
    // Receive the nonce from the secure server.
    var nonce = ...

    // Create an instance of a manager.
    var integrityManager = new IntegrityManager();

    // Request the integrity token by providing a nonce.
    var tokenRequest = new IntegrityTokenRequest(nonce);
    var requestIntegrityTokenOperation =
        integrityManager.RequestIntegrityToken(tokenRequest);

    // Wait for PlayAsyncOperation to complete.
    yield return requestIntegrityTokenOperation;

    // Check the resulting error code.
    if (requestIntegrityTokenOperation.Error != IntegrityErrorCode.NoError)
    {
        AppendStatusLog("IntegrityAsyncOperation failed with error: " +
                requestIntegrityTokenOperation.Error);
        yield break;
    }

    // Get the response.
    var tokenResponse = requestIntegrityTokenOperation.GetResult();
}

Yerel

/// Create an IntegrityTokenRequest opaque object.
const char* nonce = RequestNonceFromServer();
IntegrityTokenRequest* request;
IntegrityTokenRequest_create(&request);
IntegrityTokenRequest_setNonce(request, nonce);

/// Prepare an IntegrityTokenResponse opaque type pointer and call
/// IntegerityManager_requestIntegrityToken().
IntegrityTokenResponse* response;
IntegrityErrorCode error_code =
        IntegrityManager_requestIntegrityToken(request, &response);

/// ...
/// Proceed to polling iff error_code == INTEGRITY_NO_ERROR
if (error_code != INTEGRITY_NO_ERROR)
{
    /// Remember to call the *_destroy() functions.
    return;
}
/// ...
/// Use polling to wait for the async operation to complete.
/// Note, the polling shouldn't block the thread where the IntegrityManager
/// is running.

IntegrityResponseStatus response_status;

/// Check for error codes.
IntegrityErrorCode error_code =
        IntegrityTokenResponse_getStatus(response, &response_status);
if (error_code == INTEGRITY_NO_ERROR
    && response_status == INTEGRITY_RESPONSE_COMPLETED)
{
    const char* integrity_token = IntegrityTokenResponse_getToken(response);
    SendTokenToServer(integrity_token);
}
/// ...
/// Remember to free up resources.
IntegrityTokenRequest_destroy(request);
IntegrityTokenResponse_destroy(response);
IntegrityManager_destroy();

Entegrasyon kararının şifresini çözün ve doğrulayın

Entegrasyon kararı istediğinizde Play Integrity API imzalı bir yanıt jetonu. İsteğinize eklediğiniz nonce, yanıt jetonu.

Jeton biçimi

Jeton, iç içe yerleştirilmiş bir JSON Web Token'dır (JWT) JSON Web Şifreleme'dir (JWE) JSON Web Signature (JWS) arasındaki farklar hakkında daha fazla bilgi edinin. JWE ve JWS bileşenleri kompakt serileştirme ,

Şifreleme / imzalama algoritmaları çeşitli JWT'lerde iyi şekilde desteklenmektedir. gibi çeşitli özelliklerden bahsedeceğiz:

  • JWE, A256KW'yu şunun için kullanır: alg ve enc için A256GCM

  • JWS, ES256 kullanır.

Google'ın sunucularında şifre çözme ve doğrulama (önerilir)

Play Integrity API, cihazınızda entegrasyon kararının şifresini çözmenizi ve doğrulamanızı sağlar. Uygulamanızın güvenliğini artıran Google sunucuları. Bunu yapmak için şu adımları tamamlayın: için şu adımları izleyin:

  1. Hizmet hesabı oluşturma bu verileri paylaşmıştık.
  2. Uygulamanızın sunucusunda hizmet hesabınızdan erişim jetonunu getirin kimlik bilgilerini playintegrity kapsamını kullanarak belirleyin ve şu isteği gönderin:

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. JSON yanıtını okuyun.

Yerel olarak şifre çözme ve doğrulama

Yanıt şifreleme anahtarlarınızı yönetmeyi ve indirmeyi seçerseniz: kendi güvenli sunucu ortamınızda döndürülen jetonun şifresini çözün ve doğrulayın. Döndürülen jetonu IntegrityTokenResponse#token() kullanarak alabilirsiniz yöntemidir.

Aşağıdaki örnekte, AES anahtarının ve DER kodlamalı genel değerin nasıl çözüleceği gösterilmektedir Play Console'dan dile özgü imza doğrulamasına yönelik EC anahtarı (bizim örneğimizde Java programlama dili) tuşlarını kullanabilirsiniz. Not anahtarların, varsayılan işaretler kullanılarak base64 olarak kodlanması.

Kotlin

// base64OfEncodedDecryptionKey is provided through Play Console.
var decryptionKeyBytes: ByteArray =
    Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT)

// Deserialized encryption (symmetric) key.
var decryptionKey: SecretKey = SecretKeySpec(
    decryptionKeyBytes,
    /* offset= */ 0,
    AES_KEY_SIZE_BYTES,
    AES_KEY_TYPE
)

// base64OfEncodedVerificationKey is provided through Play Console.
var encodedVerificationKey: ByteArray =
    Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT)

// Deserialized verification (public) key.
var verificationKey: PublicKey = KeyFactory.getInstance(EC_KEY_TYPE)
    .generatePublic(X509EncodedKeySpec(encodedVerificationKey))

Java

// base64OfEncodedDecryptionKey is provided through Play Console.
byte[] decryptionKeyBytes =
    Base64.decode(base64OfEncodedDecryptionKey, Base64.DEFAULT);

// Deserialized encryption (symmetric) key.
SecretKey decryptionKey =
    new SecretKeySpec(
        decryptionKeyBytes,
        /* offset= */ 0,
        AES_KEY_SIZE_BYTES,
        AES_KEY_TYPE);

// base64OfEncodedVerificationKey is provided through Play Console.
byte[] encodedVerificationKey =
    Base64.decode(base64OfEncodedVerificationKey, Base64.DEFAULT);
// Deserialized verification (public) key.
PublicKey verificationKey =
    KeyFactory.getInstance(EC_KEY_TYPE)
        .generatePublic(new X509EncodedKeySpec(encodedVerificationKey));

Ardından, ilk olarak bütünlük jetonunun (JWE bölümü) şifresini çözmek için bu anahtarları kullanın ve ardından iç içe yerleştirilmiş JWS bölümünü doğrulayın ve çıkarın.

Kotlin

val jwe: JsonWebEncryption =
    JsonWebStructure.fromCompactSerialization(integrityToken) as JsonWebEncryption
jwe.setKey(decryptionKey)

// This also decrypts the JWE token.
val compactJws: String = jwe.getPayload()

val jws: JsonWebSignature =
    JsonWebStructure.fromCompactSerialization(compactJws) as JsonWebSignature
jws.setKey(verificationKey)

// This also verifies the signature.
val payload: String = jws.getPayload()

Java

JsonWebEncryption jwe =
    (JsonWebEncryption)JsonWebStructure
        .fromCompactSerialization(integrityToken);
jwe.setKey(decryptionKey);

// This also decrypts the JWE token.
String compactJws = jwe.getPayload();

JsonWebSignature jws =
    (JsonWebSignature) JsonWebStructure.fromCompactSerialization(compactJws);
jws.setKey(verificationKey);

// This also verifies the signature.
String payload = jws.getPayload();

Elde edilen yük, bütünlük içeren bir düz metin jetonudur karar verebilirsiniz.