Na tej stronie opisujemy wykonywanie standardowych żądań do interfejsu API w celu oceny integralności, które są obsługiwane na Androidzie 5.0 (poziom interfejsu API 21) lub nowszym. Możesz utworzyć standardowy Żądanie do interfejsu API dotyczące oceny integralności za każdym razem, gdy aplikacja wykonuje wywołanie serwera pod kątem autentyczności interakcji.
Omówienie
Żądanie standardowe składa się z 2 części:
- Przygotuj dostawcę tokena integralności: musisz wywołać metodę Integrity API, aby przygotować dostawcę tokena integralności na długo, zanim zajdzie taka potrzeba aby uzyskać ocenę integralności. Możesz to zrobić na przykład wtedy, gdy Twoja aplikacja jest uruchamiana lub w tle, zanim będzie potrzebna ocena integralności.
- Wysyłaj żądanie tokena integralności (na żądanie): za każdym razem, gdy aplikacja utworzy serwer pojawia się prośba o token integralności, i wysyłają na serwer backendu aplikacji w celu odszyfrowania i weryfikacji. Serwer backendu może wtedy podjąć odpowiednie działania.
Przygotuj dostawcę tokena integralności (jeden raz):
- Aplikacja wywołuje dostawcę tokena integralności za pomocą projektu Google Cloud numer.
- Aplikacja przechowuje dostawcę tokena integralności w pamięci na potrzeby dalszego działania i sprawdzania atestu.
Wysyłanie żądania tokena integralności (na żądanie):
- W przypadku działania użytkownika, które musi być chronione, aplikacja oblicza hasz. (za pomocą dowolnego odpowiedniego algorytmu szyfrowania, np. SHA256) żądania, które ma zostać wysłane.
- Aplikacja prosi o token integralności, przekazując hasz żądania.
- Twoja aplikacja otrzymuje podpisany i zaszyfrowany token integralności z Google Play. Integrity API.
- Aplikacja przekazuje token integralności do backendu aplikacji.
- Backend aplikacji wysyła token do serwera Google Play. Google Play Serwer odszyfrowuje i weryfikuje ocenę, zwracając wyniki do źródła aplikacji z backendem.
- Backend aplikacji decyduje, co zrobić dalej, na podstawie sygnałów ładunek tokena.
- Backend aplikacji wysyła do niej wyniki decyzji.
Przygotowywanie dostawcy tokena integralności (jeden wyłączony)
Zanim prześlesz do Google Play standardową prośbę o ocenę integralności, musisz przygotować (czyli „rozgrzewać”) dostawcę tokena integralności. Dzięki temu Google Graj, aby inteligentnie przechowywać w pamięci podręcznej informacje o częściowym atestach na urządzeniu w celu skrócenie czasu oczekiwania na ścieżce krytycznej przy wysyłaniu żądania dla ocenę integralności. Ponowne przygotowanie dostawcy tokena pozwala ograniczyć liczbę powtarzania testy integralności intensywnie korzystające z zasobów, co wykona kolejną ocenę integralności aby poprosić o bardziej aktualne informacje.
Możesz przygotować dostawcę tokena integralności:
- Po uruchomieniu aplikacji (np. przy uruchomieniu „na zimno”). Przygotowuję dostawcę tokena jest asynchroniczny, więc nie będzie wpływać na czas uruchamiania. Ta opcja spowoduje działa dobrze, jeśli planujesz prośbę o ocenę spójności wkrótce po jest uruchamiana, np. gdy użytkownik się loguje lub gracz dołącza do gry.
- Kiedy aplikacja jest uruchomiona (np. podczas uruchamiania częściowo z pamięci). Pamiętaj jednak, że każda aplikacja może przygotować token integralności maksymalnie 5 razy na minutę.
- w dowolnym momencie w tle, gdy chcesz przygotować token z wyprzedzeniem; żądania oceny integralności.
Aby przygotować dostawcę tokena integralności, wykonaj te czynności:
- Utwórz
StandardIntegrityManager
w sposób opisany w przykładach poniżej. - Zbuduj
PrepareIntegrityTokenRequest
udostępniający Google Cloud numeru projektu za pomocą metodysetCloudProjectNumber()
. - Użyj menedżera, aby wywołać funkcję
prepareIntegrityToken()
i podaćPrepareIntegrityTokenRequest
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));
Jedność
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(); }
Rodzimy użytkownik
/// 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);
Chroń żądania przed manipulacją (zalecane)
Gdy sprawdzasz działania użytkownika w aplikacji za pomocą interfejsu Play Integrity API,
może wykorzystać pole requestHash
do ograniczenia ataków z powodu manipulacji. Dla:
na przykład gra może chcieć zgłosić wynik gracza do backendu gry
, a Twój serwer chce mieć pewność, że ten wynik nie został zmieniony przez
serwer proxy. Interfejs Play Integrity API zwraca wartość ustawioną w polu
requestHash
w podpisanej odpowiedzi dotyczącej integralności. Bez
requestHash
, token integralności będzie powiązany tylko z urządzeniem, ale nie z urządzeniem
konkretnego żądania, co stwarza ryzyko ataku. Poniżej
instrukcje pozwalają skutecznie korzystać z pola requestHash
:
Gdy poprosisz o ocenę integralności:
- Oblicz podsumowanie wszystkich odpowiednich parametrów żądania (np. SHA256 stabilnej wersji
żądania serializacji) z działania użytkownika lub żądania serwera,
co się dzieje. Maksymalna długość wartości ustawionej w polu
requestHash
to 500 bajtów. Umieść w plikurequestHash
wszystkie żądania z aplikacji, które są kluczowe lub powiązane z sprawdzanym lub chronionym działaniem. Token integralności zawiera polerequestHash
w sposób dosłowny, więc ciąg znaków mogą zwiększyć rozmiar żądania. - przekazać skrót w postaci pola
requestHash
do interfejsu Play Integrity API; uzyskać token integralności.
Gdy otrzymasz ocenę integralności:
- Zdekoduj token integralności i wyodrębnij pole
requestHash
. - Oblicz podsumowanie żądania w taki sam sposób jak w aplikacji (np. SHA256 stabilnego żądania serializacji).
- Porównaj skróty po stronie aplikacji i serwera. Jeśli nie są zgodne, żądanie nie jest wiarygodne.
Wysyłanie prośby o ocenę integralności (na żądanie)
Po przygotowaniu dostawcy tokena integralności możesz zacząć wysyłać żądania oceny integralności pochodzące z Google Play. Aby to zrobić:
- Uzyskaj
StandardIntegrityTokenProvider
w sposób opisany powyżej. - Utwórz obiekt
StandardIntegrityTokenRequest
, podając hasz żądania działanie użytkownika, które chcesz chronić za pomocą metodysetRequestHash
. - Użyj dostawcy tokena integralności, aby wywołać
request()
, podając wartośćStandardIntegrityTokenRequest
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));
Jedność
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(); }
Rodzimy użytkownik
/// 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();
Odszyfruj i zweryfikuj ocenę integralności
Gdy poprosisz o ocenę integralności, interfejs Play Integrity API wygeneruje zaszyfrowany token odpowiedzi. Aby uzyskać oceny integralności urządzenia, musisz odszyfrować token integralności na serwerach Google. W tym celu wykonaj następujące czynności:
- Tworzenie konta usługi w projekcie Google Cloud połączonym z Twoją aplikacją.
Z serwera aplikacji pobierz token dostępu ze swojego konta usługi dane logowania w zakresie playintegrity i wyślij to żądanie:
playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
Przeczytaj odpowiedź JSON.
Powstały w ten sposób ładunek to zwykły token tekstowy zawierający integralność .
Automatyczna ochrona przed ponownym odtwarzaniem
Aby ograniczyć ataki typu „powtórka”, Google Play automatycznie dba o to, aby każda tokenu integralności nie można wielokrotnie użyć. Wielokrotne próba odszyfrowania ten sam token spowoduje, że wyniki będą puste.