Esegui una richiesta API standard

Questa pagina descrive le richieste API standard per gli esiti relativi all'integrità, che sono supportati su Android 5.0 (livello API 21) o versioni successive. Puoi creare un modello Richiesta API per un esito relativo all'integrità ogni volta che la tua app effettua una chiamata al server per verificare se l'interazione è autentica.

Panoramica

Diagramma di sequenza che mostra il design generale di Play Integrity
API

Una richiesta standard è costituita da due parti:

  • Prepara il provider di token di integrità (una tantum): devi chiamare il metodo l'API Integrity per preparare il provider di token di integrità molto prima di te per ottenere l'esito relativo all'integrità. Ad esempio, puoi farlo quando la tua app o in background prima che sia necessario l'esito relativo all'integrità.
  • Richiedere un token di integrità (on demand): ogni volta che la tua app crea un server la richiesta di verifica è autentica, richiedi un token di integrità e invialo al server di backend dell'app per la decriptazione e la verifica. Successivamente, il tuo server di backend potrà decidere come agire.

Prepara il provider di token di integrità (una tantum):

  1. La tua app chiama il provider di token di integrità con il tuo progetto Google Cloud numero.
  2. La tua app conserva in memoria il provider di token di integrità per ulteriore di controllo dell'attestazione.

Richiedi un token di integrità (on demand):

  1. La tua app calcola l'hash per l'azione dell'utente che deve essere protetta (utilizzando qualsiasi algoritmo hash adatto, come SHA256) della richiesta da effettuare.
  2. La tua app richiede un token di integrità, passando l'hash della richiesta.
  3. La tua app riceve il token di integrità firmato e criptato da Google Play API Integrity.
  4. L'app passa il token di integrità al backend dell'app.
  5. Il backend dell'app invia il token a un server Google Play. Google Play decripta e verifica l'esito, restituendo i risultati al database dell'app di un backend cloud.
  6. Il backend dell'app decide come procedere, in base agli indicatori contenuti nelle il payload del token.
  7. Il backend dell'app invia i risultati della decisione all'app.

Prepara il provider di token di integrità (una tantum)

Prima di presentare una richiesta standard di esito relativo all'integrità da Google Play, Devi preparare (o "riavviare") il fornitore di token di integrità. Ciò consente a Google Memorizza nella cache in modo intelligente le informazioni di attestazione parziale sul dispositivo al fine di: diminuirà la latenza sul percorso critico quando richiedi un esito relativo all'integrità. Preparare di nuovo il provider di token è un modo per ripetere meno dell'integrità delle risorse, che determinerà il successivo esito relativo all'integrità che richiedete più aggiornamenti.

Potresti preparare il fornitore di token di integrità:

  • All'avvio dell'app (ad esempio all'avvio a freddo). Preparazione del provider di token è asincrono e non influirà quindi sull'avvio. Questa opzione funzionano bene se prevedi di presentare una richiesta di esito relativo all'integrità poco dopo dell'app, ad esempio quando un utente esegue l'accesso o un giocatore partecipa a un gioco.
  • All'apertura dell'app (ad esempio durante un avvio a caldo). Tuttavia, tieni presente che ogni app l'istanza può preparare il token di integrità solo fino a cinque volte al minuto.
  • In qualsiasi momento in background quando vuoi preparare il token in anticipo di una richiesta di esito relativo all'integrità.

Per preparare il fornitore di token di integrità, segui questi passaggi:

  1. Crea un StandardIntegrityManager, come mostrato negli esempi seguenti.
  2. Crea un PrepareIntegrityTokenRequest, fornendo il servizio Google Cloud il numero di progetto con il metodo setCloudProjectNumber().
  3. Utilizza l'amministratore per chiamare prepareIntegrityToken(), fornendo il metodo PrepareIntegrityTokenRequest.
di Gemini Advanced.

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));

Unity

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();
}

Nativo

/// 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);

Proteggi le richieste da manomissioni (opzione consigliata)

Quando controlli un'azione utente nella tua app con l'API Play Integrity, può sfruttare il campo requestHash per mitigare gli attacchi di manomissione. Per Ad esempio, un gioco potrebbe voler segnalare il punteggio del giocatore al backend server web, che vuole assicurarsi che questo punteggio non sia stato manomesso un server proxy. L'API Play Integrity restituisce il valore impostato nel Campo requestHash, all'interno della risposta relativa all'integrità firmata. Senza il parametro requestHash, il token di integrità verrà associato solo al dispositivo, ma non a la richiesta specifica, il che apre la possibilità di un attacco. Le seguenti istruzioni descrivono come utilizzare il campo requestHash in modo efficace:

Quando richiedi un esito relativo all'integrità:

  • Calcola un digest di tutti i parametri della richiesta pertinenti (ad es. SHA256 di un modello serializzazione) dall'azione utente o dalla richiesta del server che in cui ciò che accade. Il valore impostato nel campo requestHash ha una lunghezza massima di 500 byte. Includi nel requestHash i dati delle richieste di app che sono fondamentali o pertinente all'azione che stai controllando o proteggendo. La Il campo requestHash è incluso nel testo del token di integrità, quindi possono aumentare le dimensioni della richiesta.
  • Fornire il digest come campo requestHash all'API Play Integrity e ottenere il token di integrità.
di Gemini Advanced.

Quando ricevi un esito relativo all'integrità:

  • Decodifica il token di integrità ed estrai il campo requestHash.
  • Calcola un digest della richiesta come fai nell'app (ad es. SHA256 di una serializzazione di richiesta stabile).
  • Confronta le sintesi lato app e lato server. Se non corrispondono, della richiesta non è attendibile.
di Gemini Advanced.

Richiedere un esito relativo all'integrità (on demand)

Dopo aver preparato il fornitore di token di integrità, puoi iniziare a richiedere esiti relativi all'integrità da Google Play. Per farlo, segui questi passaggi:

  1. Ottieni un StandardIntegrityTokenProvider, come mostrato sopra.
  2. Crea un StandardIntegrityTokenRequest, fornendo l'hash della richiesta di l'azione dell'utente che vuoi proteggere tramite il metodo setRequestHash.
  3. Usa il provider di token di integrità per chiamare request(), fornendo il token 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));

Unity

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();
}

Nativo

/// 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();

Decripta e verifica l'esito relativo all'integrità

Dopo aver richiesto un esito relativo all'integrità, l'API Play Integrity fornisce un il token di risposta criptato. Per ottenere gli esiti relativi all'integrità del dispositivo, devi decriptare il token di integrità sui server di Google. Per farlo, segui questi passaggi:

  1. Crea un account di servizio all'interno del progetto Google Cloud collegato alla tua app.
  2. Sul server dell'app, recupera il token di accesso dal tuo account di servizio utilizzando l'ambito playintegrity ed effettua la richiesta seguente:

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. Leggi la risposta JSON.

Il payload risultante è un token di testo normale che contiene integrità e decisioni.

Protezione dalla riproduzione automatica

Per mitigare gli attacchi di ripetizione, Google Play garantisce automaticamente che ogni il token di integrità non può essere riutilizzato molte volte. Si sta tentando di decriptare ripetutamente nello stesso token produrranno esiti vuoti.