تقديم طلب عادي من واجهة برمجة التطبيقات

تصف هذه الصفحة عملية إنشاء طلبات بيانات عادية من واجهة برمجة التطبيقات للحصول على بيانات السلامة، والتي متاحة على نظام التشغيل Android 5.0 (المستوى 21 لواجهة برمجة التطبيقات) أو الإصدارات الأحدث. يمكنك وضع معيار طلب بيانات من واجهة برمجة التطبيقات للحصول على بيان السلامة عندما يجري تطبيقك اتصالاً بالخادم للتحقق مما إذا كان التفاعل حقيقيًا أم لا.

نظرة عامة

مخطّط بياني للتسلسل يوضّح التصميم العالي المستوى لميزة Play Integrity
واجهة برمجة التطبيقات

يتكون الطلب العادي من جزأين:

  • تحضير موفِّر الرموز المميّزة للأمان (غير مُستخدَم): عليك طلب Integrity API لإعداد موفِّر الرموز المميّزة لسلامة الأجهزة قبل الحاجة للحصول على بيان السلامة. على سبيل المثال، يمكنك إجراء ذلك عندما لا يكون تطبيقك أو التي يتم إطلاقها في الخلفية قبل الحاجة إلى بيان السلامة.
  • طلب رمز مميَّز للسلامة (عند الطلب): عندما ينشئ تطبيقك خادمًا أنك تريد التحقق من أنه حقيقي، فإنك تطلب رمز سلامة وإرساله إلى خادم الخلفية في تطبيقك لفك التشفير والتحقُّق منها. ومن ثم يمكن لخادم الخلفية تحديد طريقة التصرف.

تجهيز موفّر الرموز المميّزة للأمان (إجراء واحد)

  1. يطلب تطبيقك موفِّر الرموز المميّزة للأمان من خلال مشروعك على Google Cloud. الصف.
  2. يحتفظ تطبيقك بموفِّر السلامة في الذاكرة لإجراء المزيد من الإجراءات فحص المصادقة.

طلب رمز مميَّز للسلامة (عند الطلب):

  1. يحتسب تطبيقك التجزئة لإجراء المستخدم الذي يجب حمايته. (باستخدام أي خوارزمية تجزئة مناسبة مثل SHA256) للطلب الذي سيتم تقديمه.
  2. يطلب تطبيقك رمزًا مميّزًا للأمان، مع تمرير تجزئة الطلب.
  3. سيتلقّى تطبيقك رمز السلامة المميّز الموقَّع والمشفَّر من Play. Integrity API.
  4. يمرّر تطبيقك الرمز المميّز للسلامة إلى خلفية تطبيقك.
  5. ترسل الواجهة الخلفية لتطبيقك الرمز المميّز إلى خادم Google Play. فريق Google Play فك تشفير البيان والتحقق من صحته، وعرض النتائج إلى ملف الخلفية.
  6. تحدِّد خلفية تطبيقك كيفية المتابعة استنادًا إلى الإشارات الواردة في حمولة البيانات الخاصة بالرمز المميز.
  7. ترسل خلفية تطبيقك نتائج القرار إلى تطبيقك.

تجهيز موفّر الرموز المميّزة للأمان (غير متوفّر)

قبل تقديم طلب عادي للحصول على بيان سلامة من Google Play، يُرجى اتّباع الخطوات التالية: عليك إعداد (أو "تجهيز التجهيزات") لموفّر الرموز المميّزة للسلامة. يتيح ذلك لـ Google يمكنك التشغيل لتخزين معلومات المصادقة الجزئية في الجهاز مؤقتًا بشكل ذكي تقليل وقت الاستجابة على المسار الحرج عند تقديم طلب بيان السلامة. إنّ إعداد موفِّر الرمز المميّز مرة أخرى هو إحدى طرق التكرار بوتيرة أقل عمليات تحقق مكثّفة من سلامة الموارد والتي ستصدر بيان السلامة التالي تطلب تحديث التطبيق.

يمكنك إعداد موفّر الرموز المميّزة للأمان على النحو التالي:

  • عند تشغيل التطبيق (أي عند التشغيل على البارد) جارٍ تحضير موفِّر الرمز المميّز غير متزامن وبالتالي لن يؤثر في وقت بدء التشغيل. سيؤدي هذا الخيار إلى بشكلٍ جيد إذا كنت تخطط لتقديم طلب بيان سلامة بعد وقت قصير إطلاق تطبيق، مثلاً عندما يسجِّل مستخدم الدخول أو ينضم لاعب إلى لعبة.
  • عندما يكون التطبيق مفتوحًا (أي عند إعادة التشغيل البطيء) ومع ذلك، لاحظ أن كل تطبيق يمكن لمثيل مثالي إعداد رمز السلامة المميز لما يصل إلى 5 مرات في الدقيقة.
  • في أي وقت في الخلفية عندما تريد إعداد الرمز المميّز مسبقًا لطلب بيان السلامة.

لإعداد موفِّر خدمة الرموز المميّزة للسلامة، اتّبِع الخطوات التالية:

  1. أنشئ StandardIntegrityManager، كما هو موضّح في الأمثلة التالية.
  2. إنشاء PrepareIntegrityTokenRequest وتوفير Google Cloud رقم المشروع من خلال طريقة setCloudProjectNumber().
  3. يمكنك استخدام المدير للاتصال بـ prepareIntegrityToken()، وتوفير 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));

الانسجام

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

مدمجة مع المحتوى

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

الحماية من التلاعب في الطلبات (يُنصح به)

عند التحقّق من إجراء مستخدم في تطبيقك باستخدام Play Integrity API، يجب الاستفادة من الحقل requestHash للحد من هجمات التلاعب. بالنسبة على سبيل المثال، قد تريد لعبة إبلاغ خلفية اللعبة بنتيجة اللاعب ويريد خادمك التأكد من عدم التلاعب بهذه الدرجة من قِبل خادم وكيل. تعرض واجهة برمجة التطبيقات Play Integrity API القيمة التي حدّدتها في requestHash، داخل استجابة السلامة الموقَّعة. بدون requestHash، سيتم ربط الرمز المميّز لسلامة الجهاز فقط، وليس الطلب المحدد، مما يفتح إمكانية التعرض للهجوم. ما يلي: توضح التعليمات كيفية الاستفادة من الحقل requestHash بشكل فعال:

عند طلب بيان سلامة:

  • الحصول على ملخّص لكل مَعلمات الطلب ذات الصلة (مثل SHA256 لعنصر ثابت) طلب التسلسل) من إجراء المستخدم أو طلب الخادم الذي يحدث. الحد الأقصى لعدد الأحرف المسموح به في القيمة المحددة في الحقل requestHash 500 بايت. يُرجى تضمين أي بيانات خاصة بطلبات التطبيقات في requestHash، وهي بيانات مهمة أو وثيق الصلة بالإجراء الذي تتحقق منه أو تحميه. تشير رسالة الأشكال البيانية يتم تضمين الحقل requestHash في حرفي الرمز المميز للسلامة، على زيادة حجم الطلب.
  • قدِّم الملخّص على أنّه الحقل requestHash في واجهة برمجة التطبيقات Play Integrity API. والحصول على رمز السلامة.

عند تلقّي بيان سلامة، عليك إجراء ما يلي:

  • يجب فك ترميز الرمز المميّز للأمان، واستخراج الحقل requestHash.
  • احتساب ملخص للطلب بالطريقة نفسها المستخدَمة في التطبيق (على سبيل المثال، SHA256 لتسلسل طلب ثابت).
  • مقارنة الملخّصات من جهة التطبيق ومن جهة الخادم إذا لم يتطابقا، فسيتم أن يكون الطلب غير موثوق به.

طلب بيان السلامة (عند الطلب)

بعد إعداد موفِّر الرموز المميّزة للأمان، يمكنك البدء في طلب بيانات السلامة الصادرة عن Google Play للقيام بذلك، أكمل الخطوات التالية:

  1. يجب الحصول على StandardIntegrityTokenProvider، كما هو موضَّح أعلاه.
  2. إنشاء StandardIntegrityTokenRequest، وتوفير تجزئة الطلب إجراء المستخدم الذي تريد حمايته باستخدام الطريقة setRequestHash.
  3. استخدِم موفِّر الرموز المميّزة لسلامة الأجهزة لطلب request()، مع توفير 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));

الانسجام

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

مدمجة مع المحتوى

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

فك تشفير بيان السلامة والتحقّق منه

بعد طلب بيان السلامة، توفِّر واجهة برمجة التطبيقات Play Integrity API الرمز المميز للاستجابة المشفرة. للحصول على بيانات سلامة الجهاز، عليك فك تشفير الرمز المميز للسلامة على خوادم Google. للقيام بذلك، أكمل هذه الخطوات:

  1. إنشاء حساب خدمة ضمن مشروع Google Cloud المرتبط بتطبيقك
  2. على خادم تطبيقك، عليك جلب رمز الدخول من حساب الخدمة. بيانات الاعتماد باستخدام نطاق Playintegrity، وتقديم الطلب التالي:

    playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \
    '{ "integrity_token": "INTEGRITY_TOKEN" }'
  3. اقرأ استجابة JSON.

الحمولة الناتجة هي رمز مميّز بنص عادي يحتوي على التكامل البيانات.

الحماية التلقائية لإعادة التشغيل

للحدّ من هجمات إعادة التشغيل، يضمن Google Play تلقائيًا أنّ كل ولا يمكن إعادة استخدام رمز السلامة المميز عدة مرات. محاولة فك تشفير الملف نفس الرمز سيؤدي إلى إصدار بيان فارغ.