Bu sayfada, Android 5.0 (API düzeyi 21) veya sonraki sürümlerde desteklenen entegrasyon kararları için standart API isteklerinde bulunma açıklanmaktadır. Uygulamanız sunucu çağrısı yaptığında etkileşimin gerçek olup olmadığını kontrol etmek için entegrasyon kararı için standart bir API isteğinde bulunabilirsiniz.
Genel bakış
Standart bir istek iki bölümden oluşur:
- Bütünlük jetonu sağlayıcıyı hazırlama (bir kereye mahsus): Bütünlük jetonu sağlayıcıyı, entegrasyon kararı size ulaşmadan çok önce hazırlamak için Integrity API'yi çağırmanız gerekir. Örneğin, uygulamanız başlatıldığında veya entegrasyon kararı istenmeden önce arka planda bunu yapabilirsiniz.
- Bütünlük jetonu isteme (isteğe bağlı): Uygulamanız, gerçek olup olmadığını kontrol etmek istediğiniz sunucu isteğinde bulunduğunda, bütünlük jetonu ister ve şifre çözme ile doğrulama için bu jetonu uygulamanızın arka uç sunucusuna gönderirsiniz. Daha sonra arka uç sunucunuz ne yapacağına karar verebilir.
Bütünlük jetonu sağlayıcıyı hazırlama (tek seferlik):
- Uygulamanız, bütünlük jetonu sağlayıcıyı Google Cloud proje numaranızla çağırıyor.
- Uygulamanız, daha ayrıntılı onay kontrolü çağrıları için bütünlük jetonu sağlayıcıyı bellekte tutar.
Bütünlük jetonu isteme (isteğe bağlı):
- Uygulamanız, korunması gereken kullanıcı işlemi için yapılacak isteğin karmasını hesaplar (SHA256 gibi uygun bir karma algoritması kullanarak).
- Uygulamanız, istek karmasını ileterek bir bütünlük jetonu istiyor.
- Uygulamanız, Play Integrity API'den imzalanmış ve şifrelenmiş bütünlük jetonunu alır.
- Uygulamanız, bütünlük jetonunu uygulamanızın arka ucuna iletir.
- Uygulamanızın arka ucu, jetonu bir Google Play sunucusuna gönderir. Google Play sunucusu kararının şifresini çözüp sonuçları doğrular ve sonuçları uygulamanızın arka ucuna döndürür.
- Uygulamanızın arka ucu, jeton yükündeki sinyallere göre nasıl ilerleyeceğine karar verir.
- Uygulamanızın arka ucu, karar sonuçlarını uygulamanıza gönderir.
Bütünlük jetonu sağlayıcıyı hazırlama (tek seferlik)
Google Play'den entegrasyon kararı için standart bir istekte bulunmadan önce bütünlük jetonu sağlayıcıyı hazırlamanız (veya "ısıtmanız") gerekir. Bu sayede Google Play, entegrasyon kararı isteğinde bulunduğunuzda kritik yoldaki gecikmeyi azaltmak için cihazda kısmi onay bilgilerini akıllı bir şekilde önbelleğe alabilir. Jeton sağlayıcıyı tekrar hazırlamak, daha az kaynak ağırlıklı bütünlük kontrollerini tekrarlamanın bir yoludur. Bu sayede, talep ettiğiniz bir sonraki entegrasyon kararı daha güncel olur.
Bütünlük jetonu sağlayıcıyı hazırlayabilirsiniz:
- Uygulamanız başlatıldığında (ör. baştan başlatmada). Jeton sağlayıcıyı hazırlamak eşzamansız bir işlemdir ve bu nedenle başlatma süresini etkilemez. Bir kullanıcı oturum açtığında veya oyuncu oyuna katıldığında uygulama kullanıma sunulduktan kısa bir süre sonra entegrasyon kararı isteğinde bulunmayı planlıyorsanız bu seçenek işe yarar.
- Uygulamanız açıldığında (ör. hazır durumda başlatma sırasında). Ancak her uygulama örneğinin, bütünlük jetonunu dakikada en fazla 5 kez hazırlayabileceğini unutmayın.
- Arka planda herhangi bir zamanda, entegrasyon kararı isteğinden önce jetonu hazırlamak istediğinizde.
Bütünlük jetonu sağlayıcıyı hazırlamak için aşağıdakileri yapın:
- Aşağıdaki örneklerde gösterildiği gibi bir
StandardIntegrityManager
oluşturun. - Google Cloud proje numarasını
setCloudProjectNumber()
yöntemiyle sağlayarak birPrepareIntegrityTokenRequest
oluşturun. PrepareIntegrityTokenRequest
sağlayarakprepareIntegrityToken()
numarasını aramak için yöneticiyi kullanın.
Java
import com.google.android.gms.tasks.Task; // Create an instance of a manager. StandardIntegrityManager standardIntegrityManager = IntegrityManagerFactory.createStandard(applicationContext); StandardIntegrityTokenProvider integrityTokenProvider; long cloudProjectNumber = ...; // Prepare integrity token. Can be called once in a while to keep internal // state fresh. standardIntegrityManager.prepareIntegrityToken( PrepareIntegrityTokenRequest.builder() .setCloudProjectNumber(cloudProjectNumber) .build()) .addOnSuccessListener(tokenProvider -> { integrityTokenProvider = tokenProvider; }) .addOnFailureListener(exception -> handleError(exception));
Üçlü
IEnumerator PrepareIntegrityTokenCoroutine() { long cloudProjectNumber = ...; // Create an instance of a standard integrity manager. var standardIntegrityManager = new StandardIntegrityManager(); // Request the token provider. var integrityTokenProviderOperation = standardIntegrityManager.PrepareIntegrityToken( new PrepareIntegrityTokenRequest(cloudProjectNumber)); // Wait for PlayAsyncOperation to complete. yield return integrityTokenProviderOperation; // Check the resulting error code. if (integrityTokenProviderOperation.Error != StandardIntegrityErrorCode.NoError) { AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " + integrityTokenProviderOperation.Error); yield break; } // Get the response. var integrityTokenProvider = integrityTokenProviderOperation.GetResult(); }
Yerel
/// Initialize StandardIntegrityManager StandardIntegrityManager_init(/* app's java vm */, /* an android context */); /// Create a PrepareIntegrityTokenRequest opaque object. int64_t cloudProjectNumber = ...; PrepareIntegrityTokenRequest* tokenProviderRequest; PrepareIntegrityTokenRequest_create(&tokenProviderRequest); PrepareIntegrityTokenRequest_setCloudProjectNumber(tokenProviderRequest, cloudProjectNumber); /// Prepare a StandardIntegrityTokenProvider opaque type pointer and call /// StandardIntegrityManager_prepareIntegrityToken(). StandardIntegrityTokenProvider* tokenProvider; StandardIntegrityErrorCode error_code = StandardIntegrityManager_prepareIntegrityToken(tokenProviderRequest, &tokenProvider); /// ... /// Proceed to polling iff error_code == STANDARD_INTEGRITY_NO_ERROR if (error_code != STANDARD_INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// ... /// Use polling to wait for the async operation to complete. IntegrityResponseStatus token_provider_status; /// Check for error codes. StandardIntegrityErrorCode error_code = StandardIntegrityTokenProvider_getStatus(tokenProvider, &token_provider_status); if (error_code == STANDARD_INTEGRITY_NO_ERROR && token_provider_status == INTEGRITY_RESPONSE_COMPLETED) { /// continue to request token from the token provider } /// ... /// Remember to free up resources. PrepareIntegrityTokenRequest_destroy(tokenProviderRequest);
İstekleri, izinsiz değişikliklere karşı koru (önerilir)
Uygulamanızda bir kullanıcının yaptığı işlemleri Play Integrity API ile kontrol ederken, kurcalama saldırılarına karşı riski azaltmak için requestHash
alanından yararlanabilirsiniz. Örneğin, bir oyun, oyuncunun puanını oyunun arka uç sunucusuna bildirmek isteyebilir ve sunucunuz bu puanın bir proxy sunucu tarafından değiştirilmediğinden emin olmak isteyebilir. Play Integrity API, requestHash
alanında ayarladığınız değeri imzalı bütünlük yanıtının içinde döndürür. requestHash
olmadan bütünlük jetonu yalnızca cihaza bağlanır ancak belirli bir isteğe bağlı olmaz. Bu da saldırı olasılığını artırır. Aşağıdaki talimatlarda, requestHash
alanının etkili bir şekilde nasıl kullanılacağı açıklanmaktadır:
Entegrasyon kararı istediğinizde:
- Gerçekleşen kullanıcı işleminden veya sunucu isteğinden ilgili tüm istek parametrelerinin (ör. kararlı istek serileştirmesinin SHA256) özetini hesaplayın.
requestHash
alanında ayarlanan değerin maksimum uzunluğu 500 bayttır. Kontrol ettiğiniz veya koruduğunuz işlemle alakalı veya önemli olan tüm uygulama isteği verilerinirequestHash
bölümüne ekleyin.requestHash
alanı, bütünlük jetonuna tam olarak dahil edildiğinden uzun değerler istek boyutunu artırabilir. - Özeti Play Integrity API'ye
requestHash
alanı olarak sağlayın ve bütünlük jetonunu edinin.
Entegrasyon kararı aldığınızda:
- Bütünlük jetonunun kodunu çözün ve
requestHash
alanını çıkarın. - İsteğin özetini uygulamadakiyle aynı şekilde (ör. kararlı istek serileştirmesinin SHA256'sı) hesaplayın.
- Uygulama tarafı ve sunucu tarafı özetlerini karşılaştırın. Bunlar eşleşmezse istek güvenilir değildir.
Entegrasyon kararı isteme (isteğe bağlı)
Bütünlük jetonu sağlayıcıyı hazırladıktan sonra Google Play'den entegrasyon kararı istemeye başlayabilirsiniz. Bunun için aşağıdaki adımları uygulayın:
- Yukarıda gösterildiği gibi bir
StandardIntegrityTokenProvider
edinin. setRequestHash
yöntemi ile korumak istediğiniz kullanıcı işleminin istek karmasını sağlayarak birStandardIntegrityTokenRequest
oluşturun.StandardIntegrityTokenRequest
sağlayarakrequest()
çağrısı yapmak için bütünlük jetonu sağlayıcıyı kullanın.
Java
import com.google.android.gms.tasks.Task; StandardIntegrityTokenProvider integrityTokenProvider; // See above how to prepare integrityTokenProvider. // Request integrity token by providing a user action request hash. Can be called // several times for different user actions. String requestHash = "2cp24z..."; Task<StandardIntegrityToken> integrityTokenResponse = integrityTokenProvider.request( StandardIntegrityTokenRequest.builder() .setRequestHash(requestHash) .build()); integrityTokenResponse .addOnSuccessListener(response -> sendToServer(response.token())) .addOnFailureListener(exception -> handleError(exception));
Üçlü
IEnumerator RequestIntegrityTokenCoroutine() { StandardIntegrityTokenProvider integrityTokenProvider; // See above how to prepare integrityTokenProvider. // Request integrity token by providing a user action request hash. Can be called // several times for different user actions. String requestHash = "2cp24z..."; var integrityTokenOperation = integrityTokenProvider.Request( new StandardIntegrityTokenRequest(requestHash) ); // Wait for PlayAsyncOperation to complete. yield return integrityTokenOperation; // Check the resulting error code. if (integrityTokenOperation.Error != StandardIntegrityErrorCode.NoError) { AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " + integrityTokenOperation.Error); yield break; } // Get the response. var integrityToken = integrityTokenOperation.GetResult(); }
Yerel
/// Create a StandardIntegrityTokenRequest opaque object. const char* requestHash = ...; StandardIntegrityTokenRequest* tokenRequest; StandardIntegrityTokenRequest_create(&tokenRequest); StandardIntegrityTokenRequest_setRequestHash(tokenRequest, requestHash); /// Prepare a StandardIntegrityToken opaque type pointer and call /// StandardIntegrityTokenProvider_request(). Can be called several times for /// different user actions. See above how to prepare token provider. StandardIntegrityToken* token; StandardIntegrityErrorCode error_code = StandardIntegrityTokenProvider_request(tokenProvider, tokenRequest, &token); /// ... /// Proceed to polling iff error_code == STANDARD_INTEGRITY_NO_ERROR if (error_code != STANDARD_INTEGRITY_NO_ERROR) { /// Remember to call the *_destroy() functions. return; } /// ... /// Use polling to wait for the async operation to complete. IntegrityResponseStatus token_status; /// Check for error codes. StandardIntegrityErrorCode error_code = StandardIntegrityToken_getStatus(token, &token_status); if (error_code == STANDARD_INTEGRITY_NO_ERROR && token_status == INTEGRITY_RESPONSE_COMPLETED) { const char* integrityToken = StandardIntegrityToken_getToken(token); } /// ... /// Remember to free up resources. StandardIntegrityTokenRequest_destroy(tokenRequest); StandardIntegrityToken_destroy(token); StandardIntegrityTokenProvider_destroy(tokenProvider); StandardIntegrityManager_destroy();
Entegrasyon kararının şifresini çözün ve doğrulayın
Entegrasyon kararı istedikten sonra Play Integrity API şifrelenmiş bir yanıt jetonu sağlar. Cihaz entegrasyon kararlarını almak için Google'ın sunucularında bütünlük jetonunun şifresini çözmeniz gerekir. Bunun için aşağıdaki adımları uygulayın:
- Uygulamanıza bağlı Google Cloud projesinde bir hizmet hesabı oluşturun.
Uygulamanızın sunucusunda, playintegrity kapsamını kullanarak hizmet hesabı kimlik bilgilerinizden erişim jetonunu getirin ve aşağıdaki isteği yapın:
playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
JSON yanıtını okuyun.
Ortaya çıkan yük, bütünlük kararlarını içeren bir düz metin jetondur.
Otomatik tekrar oynatma koruması
Google Play, tekrar oynatma saldırılarını azaltmak için her bir bütünlük jetonunun birçok kez yeniden kullanılamamasını otomatik olarak sağlar. Aynı jetonun şifresini tekrar tekrar çözmeyi denerseniz boş sonuçlar alabilirsiniz.