Na tej stronie opisujemy, jak interpretować zwrócony wynik weryfikacji integralności i jak z nim pracować. Niezależnie od tego, czy wyślesz żądanie standardowe czy klasyczne, wynik weryfikacji integralności jest zwracany w tym samym formacie i zawiera podobne informacje. Ocena integralności przekazuje informacje o prawidłowości urządzeń, aplikacji i kont. Serwer aplikacji może użyć otrzymanego zasobu w odszyfrowanej i zweryfikowanej ocenie, aby określić, jak najlepiej postępować w przypadku konkretnego działania lub żądania w aplikacji.
Format zwracanej oceny integralności
Ładunek to zwykły tekst JSON, który zawiera sygnały integralności oraz informacje dostarczone przez dewelopera.
Ogólna struktura ładunku jest taka:
{ "requestDetails": { ... }, "appIntegrity": { ... }, "deviceIntegrity": { ... }, "accountDetails": { ... }, "environmentDetails": { ... } }
Zanim sprawdzisz poszczególne wyniki oceny integralności, musisz najpierw upewnić się, że wartości w polu requestDetails
są zgodne z wartościami z pierwotnej prośby. Sekcje poniżej zawierają szczegółowe opisy poszczególnych pól.
Pole Szczegóły żądania
Pole requestDetails
zawiera informacje o żądaniu, w tym informacje podane przez dewelopera w polu requestHash
w przypadku żądań standardowych i w polu nonce
w przypadku żądań klasycznych.
W przypadku standardowych żądań do interfejsu API:
"requestDetails": { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the request. "requestPackageName": "com.package.name", // Request hash provided by the developer. "requestHash": "aGVsbG8gd29scmQgdGhlcmU", // The timestamp in milliseconds when the integrity token // was requested. "timestampMillis": "1675655009345" }
Wartości te powinny być zgodne z wartościami w pierwotnej prośbie. Dlatego sprawdź część requestDetails
ładunku JSON, upewniając się, że wartości requestPackageName
i requestHash
są zgodne z wartościami wysłanymi w pierwotnym żądaniu, jak pokazano w tym fragmencie kodu:
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val requestHash = requestDetails.getString("requestHash") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
RequestDetails requestDetails = decodeIntegrityTokenResponse .getTokenPayloadExternal() .getRequestDetails(); String requestPackageName = requestDetails.getRequestPackageName(); String requestHash = requestDetails.getRequestHash(); long timestampMillis = requestDetails.getTimestampMillis(); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. || !requestHash.equals(expectedRequestHash) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
W przypadku żądań do klasycznego interfejsu API:
"requestDetails": { // Application package name this attestation was requested for. // Note that this field might be spoofed in the middle of the // request. "requestPackageName": "com.package.name", // base64-encoded URL-safe no-wrap nonce provided by the developer. "nonce": "aGVsbG8gd29scmQgdGhlcmU", // The timestamp in milliseconds when the request was made // (computed on the server). "timestampMillis": "1617893780" }
Wartości te powinny być zgodne z wartościami w pierwotnej prośbie. Dlatego sprawdź część requestDetails
ładunku JSON, upewniając się, że requestPackageName
i nonce
są zgodne z tym, co zostało wysłane w pierwotnym żądaniu, jak pokazano w tym fragmencie kodu:
Kotlin
val requestDetails = JSONObject(payload).getJSONObject("requestDetails") val requestPackageName = requestDetails.getString("requestPackageName") val nonce = requestDetails.getString("nonce") val timestampMillis = requestDetails.getLong("timestampMillis") val currentTimestampMillis = ... // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Java
JSONObject requestDetails = new JSONObject(payload).getJSONObject("requestDetails"); String requestPackageName = requestDetails.getString("requestPackageName"); String nonce = requestDetails.getString("nonce"); long timestampMillis = requestDetails.getLong("timestampMillis"); long currentTimestampMillis = ...; // Ensure the token is from your app. if (!requestPackageName.equals(expectedPackageName) // Ensure the token is for this specific request. See 'Generate a nonce' // section of the doc on how to store/compute the expected nonce. || !nonce.equals(expectedNonce) // Ensure the freshness of the token. || currentTimestampMillis - timestampMillis > ALLOWED_WINDOW_MILLIS) { // The token is invalid! See below for further checks. ... }
Pole Integralność aplikacji
Pole appIntegrity
zawiera informacje o pakiecie.
"appIntegrity": { // PLAY_RECOGNIZED, UNRECOGNIZED_VERSION, or UNEVALUATED. "appRecognitionVerdict": "PLAY_RECOGNIZED", // The package name of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. "packageName": "com.package.name", // The sha256 digest of app certificates (base64-encoded URL-safe). // This field is populated iff appRecognitionVerdict != UNEVALUATED. "certificateSha256Digest": ["6a6a1474b5cbbb2b1aa57e0bc3"], // The version of the app. // This field is populated iff appRecognitionVerdict != UNEVALUATED. "versionCode": "42" }
appRecognitionVerdict
może mieć te wartości:
PLAY_RECOGNIZED
- Aplikacja i certyfikat odpowiadają wersjom rozpowszechnianym w Google Play.
UNRECOGNIZED_VERSION
- Nazwa certyfikatu lub pakietu nie odpowiada rekordom Google Play.
UNEVALUATED
- Integralność aplikacji nie została określona. Pominięto niezbędny wymóg, np. urządzenie nie było wystarczająco godne zaufania.
Aby mieć pewność, że token został wygenerowany przez aplikację utworzoną przez Ciebie, sprawdź, czy integralność aplikacji jest zgodna z oczekiwaniami, jak pokazano w tym fragmencie kodu:
Kotlin
val appIntegrity = JSONObject(payload).getJSONObject("appIntegrity") val appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict") if (appRecognitionVerdict == "PLAY_RECOGNIZED") { // Looks good! }
Java
JSONObject appIntegrity = new JSONObject(payload).getJSONObject("appIntegrity"); String appRecognitionVerdict = appIntegrity.getString("appRecognitionVerdict"); if (appRecognitionVerdict.equals("PLAY_RECOGNIZED")) { // Looks good! }
Możesz też ręcznie sprawdzić nazwę pakietu aplikacji, jej wersję i certyfikaty.
Pole integralności urządzenia
Pole deviceIntegrity
może zawierać pojedynczą wartość,
deviceRecognitionVerdict
, która ma co najmniej 1 etykietę określającą, jak dobrze urządzenie może egzekwować integralność aplikacji. Jeśli urządzenie nie spełnia kryteriów żadnej etykiety, pole deviceIntegrity
pomija deviceRecognitionVerdict
.
"deviceIntegrity": { // "MEETS_DEVICE_INTEGRITY" is one of several possible values. "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"] }
Domyślnie deviceRecognitionVerdict
może zawierać:
MEETS_DEVICE_INTEGRITY
- Aplikacja działa na oryginalnym i certyfikowanym urządzeniu z Androidem. W Androidzie 13 i nowszych wersjach istnieje sprzętowe potwierdzenie, że program rozruchowy urządzenia jest zablokowany, a załadowany system operacyjny Android to certyfikowany obraz producenta urządzenia.
- Puste (pusta wartość)
- Aplikacja działa na urządzeniu, na którym pojawiły się oznaki ataku (np. punkt zaczepienia w interfejsie API) lub naruszenia systemu (np. dostęp do roota), albo aplikacja nie działa na urządzeniu fizycznym (tylko np. na emulatorze, który nie przeszedł testów integralności Google Play).
Aby mieć pewność, że token pochodzi z zaufanego urządzenia, sprawdź, czy deviceRecognitionVerdict
jest zgodny z oczekiwaniami, jak pokazano w tym fragmencie kodu:
Kotlin
val deviceIntegrity = JSONObject(payload).getJSONObject("deviceIntegrity") val deviceRecognitionVerdict = if (deviceIntegrity.has("deviceRecognitionVerdict")) { deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() } else { "" } if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
Java
JSONObject deviceIntegrity = new JSONObject(payload).getJSONObject("deviceIntegrity"); String deviceRecognitionVerdict = deviceIntegrity.has("deviceRecognitionVerdict") ? deviceIntegrity.getJSONArray("deviceRecognitionVerdict").toString() : ""; if (deviceRecognitionVerdict.contains("MEETS_DEVICE_INTEGRITY")) { // Looks good! }
Jeśli masz problemy z tym, że urządzenie testowe nie spełnia wymagań dotyczących integralności urządzenia, upewnij się, że jest na nim zainstalowany ROM fabryczny (np. zresetuj urządzenie) i że program rozruchowy jest zablokowany. Możesz też utworzyć testy interfejsu Play Integrity API w Konsoli Play.
Etykiety urządzeń warunkowych
Jeśli Twoja aplikacja jest udostępniana w Grach Google Play na PC, element
deviceRecognitionVerdict
może też zawierać tę etykietę:
MEETS_VIRTUAL_INTEGRITY
- Aplikacja działa w emulatorze z Androidem i Usługami Google Play. Emulator przeszedł testy integralności systemu i spełnia podstawowe wymagania dotyczące zgodności dla urządzeń z Androidem.
Opcjonalne informacje o urządzeniu i przywracanie urządzenia
Jeśli wyrazisz zgodę na otrzymywanie dodatkowych etykiet w ocenie integralności, pole deviceRecognitionVerdict
może zawierać te dodatkowe etykiety:
MEETS_BASIC_INTEGRITY
- Aplikacja działa na urządzeniu, które przeszło podstawowe testy integralności systemu.
Program rozruchowy urządzenia może być zablokowany lub odblokowany, a stan uruchamiania może być zweryfikowany lub niezweryfikowany. Urządzenie może nie mieć certyfikatu, w którym to przypadku Google nie może zapewnić bezpieczeństwa, prywatności ani zgodności aplikacji. W przypadku Androida 13 i nowszych wersji
MEETS_BASIC_INTEGRITY
werdykt wymaga tylko, aby główny element zaufania atestu był dostarczany przez Google. MEETS_STRONG_INTEGRITY
- Aplikacja działa na oryginalnym i certyfikowanym urządzeniu z Androidem, które ma najnowsze aktualizacje zabezpieczeń.
- W przypadku Androida 13 i nowszych wersji
MEETS_STRONG_INTEGRITY
wymagaMEETS_DEVICE_INTEGRITY
aktualizacji zabezpieczeń w ciągu ostatniego roku dla wszystkich partycji urządzenia, w tym poprawki partycji systemu operacyjnego Android i poprawki partycji dostawcy. - W przypadku Androida 12 i starszych wersji
MEETS_STRONG_INTEGRITY
wymaga tylko dowodu integralności rozruchu wspieranego sprzętowo i nie wymaga, aby urządzenie miało najnowszą aktualizację zabezpieczeń. Dlatego podczas korzystania zMEETS_STRONG_INTEGRITY
zalecamy uwzględnianie w poludeviceAttributes
wersji pakietu Android SDK.
- W przypadku Androida 13 i nowszych wersji
Pojedyncze urządzenie może zwrócić wiele etykiet urządzenia w odpowiedzi dotyczącej integralności urządzenia, jeśli zostaną spełnione kryteria każdej z nich.
Atrybuty urządzenia
Możesz też wyrazić zgodę na otrzymywanie atrybutów urządzenia, które informują o wersji pakietu Android SDK systemu Android działającego na urządzeniu. W przyszłości może zostać rozszerzona o inne atrybuty urządzenia.
Wartość wersji pakietu SDK to numer wersji pakietu Android SDK zdefiniowany w Build.VERSION_CODES
. Wersja pakietu SDK nie jest sprawdzana, jeśli pominięto niezbędny wymóg. W takim przypadku pole sdkVersion
nie jest ustawione, więc pole deviceAttributes
jest puste.
Może się tak zdarzyć, jeśli:
- Urządzenie nie jest wystarczająco zaufane.
- Na urządzeniu wystąpiły problemy techniczne.
Jeśli zdecydujesz się otrzymywać deviceAttributes
, pole deviceIntegrity
będzie zawierać to dodatkowe pole:
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "deviceAttributes": { // 33 is one possible value, which represents Android 13 (Tiramisu). "sdkVersion": 33 } }
Jeśli wersja pakietu SDK nie zostanie oceniona, pole deviceAttributes
będzie miało taką wartość:
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "deviceAttributes": {} // sdkVersion field is not set. }
Ostatnia aktywność na urządzeniu
Możesz też włączyć funkcję „Ostatnia aktywność na urządzeniu”, która informuje, ile razy w ciągu ostatniej godziny Twoja aplikacja wysłała żądanie tokena integralności na określone urządzenie. Za pomocą tej funkcji możesz chronić swoją aplikację przed nadaktywnymi urządzeniami działającymi w nietypowy sposób mogący wskazywać na trwający atak. Możesz określić, w jakim stopniu ufasz poszczególnym poziomom ostatniej aktywności na urządzeniu, na podstawie tego, ile razy Twoja aplikacja zainstalowana na typowym urządzeniu powinna wysyłać żądanie tokena integralności w ciągu godziny.
Jeśli wyrazisz zgodę na otrzymywanie recentDeviceActivity
, pole deviceIntegrity
będzie zawierać 2 wartości:
"deviceIntegrity": { "deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"], "recentDeviceActivity": { // "LEVEL_2" is one of several possible values. "deviceActivityLevel": "LEVEL_2" } }
Definicje deviceActivityLevel
różnią się w zależności od trybu i mogą mieć jedną z tych wartości:
Poziom ostatniej aktywności na urządzeniu | Standardowe żądania tokena integralności interfejsu API na tym urządzeniu w ciągu ostatniej godziny na aplikację | Żądania tokena integralności klasycznego interfejsu API na tym urządzeniu w ciągu ostatniej godziny na aplikację |
---|---|---|
LEVEL_1 (najniższa) |
10 lub mniej | 5 lub mniej |
LEVEL_2 |
Od 11 do 25 | Od 6 do 10 |
LEVEL_3 |
26–50 | Od 11 do 15 |
LEVEL_4 (najwyższy) |
Ponad 50 | Ponad 15 |
UNEVALUATED |
Ostatnia aktywność na urządzeniach nie została oceniona. Może się tak zdarzyć, ponieważ:
|
Wycofanie urządzenia (beta)
Możesz też włączyć przywoływanie danych z urządzenia, które umożliwia przechowywanie niektórych niestandardowych danych dotyczących poszczególnych urządzeń, które możesz niezawodnie odzyskać, gdy aplikacja zostanie ponownie zainstalowana na tym samym urządzeniu. Po wysłaniu żądania tokena integralności wykonujesz osobne wywołanie serwer-serwer, aby zmodyfikować wartości wycofania urządzenia w przypadku konkretnego urządzenia.
Jeśli wyrazisz zgodę na deviceRecall
, pole deviceIntegrity
będzie zawierać informacje o wycofaniu urządzenia, które zostały przez Ciebie ustawione dla konkretnego urządzenia:
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
"deviceRecall": {
"values": {
"bitFirst": true,
"bitSecond": false,
"bitThird": true
},
"writeDates": {
// Write time in YYYYMM format in UTC.
"yyyymmFirst": 202401,
// Note that yyyymmSecond is not set because bitSecond is false.
"yyyymmThird": 202310
}
}
}
deviceRecall
jest podzielony na 2 pola:
values
: przywróć wartości bitów, które zostały wcześniej ustawione na tym urządzeniu.writeDates
: przypomnij daty zapisu bitów w czasie UTC z dokładnością do roku i miesiąca. Data zapisu bitu wycofania będzie aktualizowana za każdym razem, gdy bit zostanie ustawiony natrue
, i usunięta, gdy bit zostanie ustawiony nafalse
.
Jeśli informacje o wycofaniu urządzenia są niedostępne, wartość wycofania urządzenia będzie pusta:
"deviceIntegrity": {
"deviceRecognitionVerdict": ["MEETS_DEVICE_INTEGRITY"],
"deviceRecall": {
"values": {},
"writeDates": {}
}
}
Pole szczegółów konta
Pole accountDetails
zawiera jedną wartość, appLicensingVerdict
, która reprezentuje stan licencji aplikacji w Google Play na koncie użytkownika zalogowanego na urządzeniu. Jeśli konto użytkownika ma licencję Play na aplikację, oznacza to, że użytkownik pobrał ją z Google Play lub kupił ją w Google Play.
"accountDetails": { // This field can be LICENSED, UNLICENSED, or UNEVALUATED. "appLicensingVerdict": "LICENSED" }
appLicensingVerdict
może mieć jedną z tych wartości:
LICENSED
- Użytkownik ma uprawnienia do korzystania z aplikacji. To znaczy, że zainstalował lub zaktualizował Twoją aplikację z Google Play na swoim urządzeniu.
UNLICENSED
- Użytkownik nie ma uprawnień do korzystania z aplikacji. Może się tak zdarzyć, jeśli np. zainstaluje ją z innego urządzenia lub nie pozyska jej z Google Play. Aby rozwiązać ten problem, możesz wyświetlić użytkownikom okno GET_LICENSED.
UNEVALUATED
Szczegóły dotyczące licencji nie zostały określone, ponieważ pominięto niezbędny wymóg.
Może się tak zdarzyć z kilku powodów. Oto niektóre z nich:
- Urządzenie nie jest wystarczająco zaufane.
- Google Play nie rozpoznaje wersji aplikacji zainstalowanej na urządzeniu.
- Użytkownik nie jest zalogowany w Google Play.
Aby sprawdzić, czy użytkownik ma uprawnienia do korzystania z Twojej aplikacji, sprawdź, czy wartość appLicensingVerdict
jest zgodna z oczekiwaną, jak pokazano w tym fragmencie kodu:
Kotlin
val accountDetails = JSONObject(payload).getJSONObject("accountDetails") val appLicensingVerdict = accountDetails.getString("appLicensingVerdict") if (appLicensingVerdict == "LICENSED") { // Looks good! }
Java
JSONObject accountDetails = new JSONObject(payload).getJSONObject("accountDetails"); String appLicensingVerdict = accountDetails.getString("appLicensingVerdict"); if (appLicensingVerdict.equals("LICENSED")) { // Looks good! }
Pole szczegółów środowiska
Możesz też włączyć dodatkowe sygnały dotyczące środowiska. Sygnał ryzyka dotyczącego dostępu do aplikacji umożliwia wykrycie, czy są uruchomione inne aplikacje, które mogą przechwytywać ekran, wyświetlać nakładki lub sterować urządzeniem. Ocena Play Protect informuje, czy usługa Google Play Protect jest włączona na urządzeniu i czy wykryła znane złośliwe oprogramowanie.
Jeśli w Konsoli Google Play włączysz ocenę ryzyka dostępu do aplikacji lub ocenę Play Protect, odpowiedź interfejsu API będzie zawierać pole environmentDetails
. Pole environmentDetails
może zawierać 2 wartości: appAccessRiskVerdict
i playProtectVerdict
.
Ocena ryzyka dotyczącego dostępu do aplikacji
Gdy włączysz tę opcję, w polu environmentDetails
w ładunku interfejsu Play Integrity API pojawi się nowa ocena ryzyka dotyczącego dostępu do aplikacji.
{
"requestDetails": { ... },
"appIntegrity": { ... },
"deviceIntegrity": { ... },
"accountDetails": { ... },
"environmentDetails": {
"appAccessRiskVerdict": {
// This field contains one or more responses, for example the following.
"appsDetected": ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
}
}
}
Jeśli oceniono ryzyko związane z dostępem do aplikacji, pole appAccessRiskVerdict
zawiera pole appsDetected
z co najmniej 1 odpowiedzią. Odpowiedzi te dzielą się na 2 grupy w zależności od źródła instalacji wykrytych aplikacji:
Aplikacje systemowe lub aplikacje z Google Play: aplikacje zainstalowane przez Google Play lub wstępnie załadowane przez producenta urządzenia w partycji systemowej urządzenia (oznaczone symbolem
FLAG_SYSTEM
). Odpowiedzi dotyczące takich aplikacji mają przedrostekKNOWN_
.Inne aplikacje: aplikacje, które nie zostały zainstalowane przez Google Play. Nie obejmuje to aplikacji wstępnie zainstalowanych na partycji systemowej przez producenta urządzenia. Odpowiedzi dotyczące takich aplikacji są poprzedzone symbolem
UNKNOWN_
.
Możesz otrzymać te odpowiedzi:
KNOWN_INSTALLED
,UNKNOWN_INSTALLED
- Zainstalowane aplikacje są zgodne z odpowiednim źródłem instalacji.
KNOWN_CAPTURING
,UNKNOWN_CAPTURING
- Uruchomione są aplikacje, które mają włączone uprawnienia umożliwiające wyświetlanie ekranu podczas działania Twojej aplikacji. Nie obejmuje to zweryfikowanych usług ułatwień dostępu znanych Google Play, które działają na urządzeniu.
KNOWN_CONTROLLING
,UNKNOWN_CONTROLLING
- Na urządzeniu działają aplikacje, które mają włączone uprawnienia umożliwiające sterowanie urządzeniem i bezpośrednie kontrolowanie danych wejściowych w Twojej aplikacji. Mogą one służyć do przechwytywania danych wejściowych i wyjściowych aplikacji. Nie dotyczy to zweryfikowanych usług ułatwień dostępu znanych Google Play, które działają na urządzeniu.
KNOWN_OVERLAYS
,UNKNOWN_OVERLAYS
- Na urządzeniu działają aplikacje, które mają włączone uprawnienia umożliwiające wyświetlanie nakładek na Twoją aplikację. Nie dotyczy to zweryfikowanych usług ułatwień dostępu znanych Google Play, które działają na urządzeniu.
- Puste (pusta wartość)
Ryzyko dotyczące dostępu do aplikacji nie jest oceniane, jeśli pominięto niezbędny wymóg. W tym przypadku pole
appAccessRiskVerdict
jest puste. Może się tak zdarzyć z kilku powodów. Oto niektóre z nich:- Urządzenie nie jest wystarczająco zaufane.
- Urządzenie nie jest telefonem, tabletem ani urządzeniem składanym.
- Urządzenie nie ma Androida 6 (poziom API 23) lub nowszego.
- Google Play nie rozpoznaje wersji aplikacji zainstalowanej na urządzeniu.
- Wersja Sklepu Google Play na urządzeniu jest nieaktualna.
- Konto użytkownika nie ma licencji Play.
- Użyto standardowego żądania z parametrem
verdictOptOut
. - Użyto żądania standardowego z wersją biblioteki interfejsu Play Integrity API, która nie obsługuje jeszcze ryzyka dotyczącego dostępu do aplikacji w przypadku żądań standardowych.
Ryzyko związane z dostępem do aplikacji automatycznie wyklucza zweryfikowane usługi ułatwień dostępu, które przeszły rozszerzoną weryfikację ułatwień dostępu w Google Play (zainstalowane przez dowolny sklep z aplikacjami na urządzeniu). „Wykluczone” oznacza, że zweryfikowane usługi ułatwień dostępu działające na urządzeniu nie będą zwracać odpowiedzi dotyczącej przechwytywania, kontrolowania ani nakładek w ocenie ryzyka związanego z dostępem aplikacji. Aby poprosić o rozszerzone sprawdzenie dostępności aplikacji w Google Play, opublikuj ją w Google Play, upewniając się, że w pliku manifestu aplikacji flaga isAccessibilityTool
ma wartość „true”, lub poproś o sprawdzenie.
Przykładowe oceny ryzyka dotyczącego dostępu do aplikacji
W tabeli poniżej znajdziesz przykłady wyników oceny ryzyka związanego z dostępem do aplikacji i ich znaczenie (tabela nie zawiera wszystkich możliwych wyników):
Przykładowa odpowiedź z oceną ryzyka dotyczącego dostępu do aplikacji | Interpretacja |
---|---|
appsDetected: ["KNOWN_INSTALLED"]
|
Na urządzeniu są zainstalowane tylko aplikacje rozpoznawane przez Google Play lub wstępnie załadowane na partycji systemowej przez producenta urządzenia. Nie działają żadne aplikacje, które mogłyby spowodować uzyskanie wyników „przechwytywanie”, „kontrolowanie” lub „nakładki”. |
appsDetected: ["KNOWN_INSTALLED", "UNKNOWN_INSTALLED", "UNKNOWN_CAPTURING"]
|
Na urządzeniu są zainstalowane aplikacje z Google Play lub wstępnie załadowane w partycji systemowej przez producenta urządzenia. Uruchomione są inne aplikacje, które mają włączone uprawnienia umożliwiające wyświetlanie ekranu lub przechwytywanie innych danych wejściowych i wyjściowych. |
appsDetected: ["KNOWN_INSTALLED", "KNOWN_CAPTURING", "UNKNOWN_INSTALLED", "UNKNOWN_CONTROLLING"]
|
Uruchomione są aplikacje z Google Play lub aplikacje systemowe, które mają włączone uprawnienia umożliwiające wyświetlanie ekranu lub przechwytywanie innych danych wejściowych i wyjściowych. Uruchomione są też inne aplikacje z włączonymi uprawnieniami, które mogą być używane do sterowania urządzeniem i bezpośredniego kontrolowania danych wejściowych w Twojej aplikacji. |
appAccessRiskVerdict: {}
|
Ryzyko związane z dostępem do aplikacji nie zostało ocenione, ponieważ pominięto niezbędny wymóg. np. urządzenie nie było wystarczająco godne zaufania. |
W zależności od poziomu ryzyka możesz zdecydować, które kombinacje ocen są akceptowalne, a w przypadku których chcesz podjąć działania. Ten fragment kodu pokazuje przykład weryfikacji, czy nie są uruchomione żadne aplikacje, które mogą rejestrować to, co widać na ekranie, lub kontrolować Twoją aplikację:
Kotlin
val environmentDetails = JSONObject(payload).getJSONObject("environmentDetails") val appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict") if (appAccessRiskVerdict.has("appsDetected")) { val appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
Java
JSONObject environmentDetails = new JSONObject(payload).getJSONObject("environmentDetails"); JSONObject appAccessRiskVerdict = environmentDetails.getJSONObject("appAccessRiskVerdict"); if (appAccessRiskVerdict.has("appsDetected")) { String appsDetected = appAccessRiskVerdict.getJSONArray("appsDetected").toString() if (!appsDetected.contains("CAPTURING") && !appsDetected.contains("CONTROLLING")) { // Looks good! } }
Naprawianie ocen ryzyka dotyczącego dostępu do aplikacji
W zależności od poziomu ryzyka możesz zdecydować, w przypadku których wyników oceny ryzyka dostępu do aplikacji chcesz podjąć działania, zanim użytkownik dokończy żądanie lub działanie. Po sprawdzeniu wyniku ryzyka dotyczącego dostępu do aplikacji możesz wyświetlić użytkownikowi opcjonalne komunikaty Google Play. Możesz wyświetlić komunikat CLOSE_UNKNOWN_ACCESS_RISK z prośbą o zamknięcie nieznanych aplikacji, które powodują wynik ryzyka dotyczącego dostępu do aplikacji, lub komunikat CLOSE_ALL_ACCESS_RISK z prośbą o zamknięcie wszystkich aplikacji (znanych i nieznanych), które powodują wynik ryzyka dotyczącego dostępu do aplikacji.
Ocena Play Protect
Gdy włączysz tę opcję, w polu environmentDetails
w ładunku interfejsu Play Integrity API pojawi się ocena dotycząca Play Protect:
"environmentDetails": {
"playProtectVerdict": "NO_ISSUES"
}
playProtectVerdict
może mieć jedną z tych wartości:
NO_ISSUES
- Usługa Play Protect jest włączona i nie wykryła na urządzeniu żadnych problemów z aplikacjami.
NO_DATA
- Ochrona Play Protect jest włączona, ale skanowanie nie zostało jeszcze przeprowadzone. Urządzenie lub aplikacja Sklep Play mogły zostać niedawno zresetowane.
POSSIBLE_RISK
- Ochrona Play Protect jest wyłączona.
MEDIUM_RISK
- Usługa Play Protect jest włączona i wykryła zainstalowane na urządzeniu potencjalnie szkodliwe aplikacje.
HIGH_RISK
- Usługa Play Protect jest włączona i wykryła na urządzeniu niebezpieczne aplikacje.
UNEVALUATED
Opinia Play Protect nie została sprawdzona.
Może się tak zdarzyć z kilku powodów. Oto niektóre z nich:
- Urządzenie nie jest wystarczająco zaufane.
- Konto użytkownika nie ma licencji Play.
Wskazówki dotyczące korzystania z oceny Play Protect
Serwer backendu aplikacji może następnie podjąć odpowiednie działania na podstawie Twojej tolerancji ryzyka. Oto kilka sugestii i potencjalnych działań użytkowników:
NO_ISSUES
- Play Protect jest włączony i nie wykrył żadnych problemów, więc nie musisz podejmować żadnych działań.
POSSIBLE_RISK
iNO_DATA
- Gdy otrzymasz te wyniki, poproś użytkownika o sprawdzenie, czy Play Protect jest włączony i czy przeprowadził skanowanie.
NO_DATA
powinien pojawiać się tylko w rzadkich przypadkach. MEDIUM_RISK
iHIGH_RISK
- W zależności od poziomu tolerancji ryzyka możesz poprosić użytkownika o uruchomienie Play Protect i podjęcie działań w odpowiedzi na ostrzeżenia Play Protect. Jeśli użytkownik nie spełnia tych wymagań, możesz zablokować mu dostęp do działania serwera.