इस पेज पर, इंटिग्रिटी के नतीजों के लिए स्टैंडर्ड एपीआई अनुरोध करने के बारे में बताया गया है. ये अनुरोध, Android 5.0 (एपीआई लेवल 21) या इसके बाद के वर्शन पर किए जा सकते हैं. जब भी आपका ऐप्लिकेशन सर्वर को कॉल कर रहा हो, तब इंटिग्रिटी के नतीजे के लिए स्टैंडर्ड एपीआई अनुरोध किया जा सकता है. इससे यह पता चलता है कि इंटरैक्शन असली है या नहीं.
खास जानकारी
स्टैंडर्ड अनुरोध में दो हिस्से होते हैं:
- इंटीग्रिटी टोकन देने वाली सेवा को तैयार करें (एक बार): आपको Integrity API को कॉल करना होगा, ताकि Integrity API से जांच के नतीजे मिलने से पहले ही, इंटीग्रिटी टोकन देने वाली सेवा तैयार हो जाए. उदाहरण के लिए, ऐसा तब किया जा सकता है, जब आपका ऐप्लिकेशन लॉन्च हो या बैकग्राउंड में, इंटिग्रिटी के फ़ैसले की ज़रूरत पड़ने से पहले.
- जब चाहें, तब इंटिग्रिटी टोकन का अनुरोध करें: जब भी आपका ऐप्लिकेशन कोई ऐसा सर्वर अनुरोध करता है जिसकी आपको पुष्टि करनी है, तब इंटिग्रिटी टोकन का अनुरोध करें. इसके बाद, इसे अपने ऐप्लिकेशन के बैकएंड सर्वर पर भेजें, ताकि इसे डिक्रिप्ट किया जा सके और इसकी पुष्टि की जा सके. इसके बाद, आपका बैकएंड सर्वर यह तय कर सकता है कि उसे क्या करना है.
इंटीग्रिटी टोकन देने वाली कंपनी को तैयार करें (एक बार):
- आपका ऐप्लिकेशन, आपके Google Cloud प्रोजेक्ट नंबर के साथ इंटिग्रिटी टोकन देने वाली कंपनी को कॉल करता है.
- आपका ऐप्लिकेशन, इंटिग्रिटी टोकन देने वाली कंपनी को मेमोरी में सेव रखता है, ताकि आगे पुष्टि करने के लिए कॉल किए जा सकें.
मांग पर इंटिग्रिटी टोकन का अनुरोध करना:
- जिस उपयोगकर्ता कार्रवाई को सुरक्षित रखना है उसके लिए, आपका ऐप्लिकेशन अनुरोध का हैश (SHA256 जैसे किसी भी सही हैश एल्गोरिदम का इस्तेमाल करके) कंप्यूट करता है.
- आपका ऐप्लिकेशन, इंटिग्रिटी टोकन का अनुरोध करता है. इसके लिए, वह अनुरोध हैश पास करता है.
- आपके ऐप्लिकेशन को Play Integrity API से, साइन किया गया और एन्क्रिप्ट (सुरक्षित) किया गया इंटिग्रिटी टोकन मिलता है.
- आपका ऐप्लिकेशन, इंटिग्रिटी टोकन को अपने ऐप्लिकेशन के बैकएंड में भेजता है.
- आपके ऐप्लिकेशन का बैकएंड, टोकन को Google Play सर्वर पर भेजता है. Google Play सर्वर, फ़ैसले को डिक्रिप्ट करता है और उसकी पुष्टि करता है. इसके बाद, नतीजे आपके ऐप्लिकेशन के बैकएंड को भेजता है.
- आपके ऐप्लिकेशन का बैकएंड, टोकन पेलोड में मौजूद सिग्नल के आधार पर यह तय करता है कि आगे क्या करना है.
- आपके ऐप्लिकेशन का बैकएंड, फ़ैसले के नतीजों को आपके ऐप्लिकेशन पर भेजता है.
इंटीग्रिटी टोकन की सेवा देने वाली कंपनी को तैयार करना (एक बार)
Google Play से इंटिग्रिटी के नतीजे का स्टैंडर्ड अनुरोध करने से पहले, आपको इंटिग्रिटी टोकन देने वाली कंपनी को तैयार करना होगा (या "वार्म अप" करना होगा). इससे Google Play, डिवाइस पर पुष्टि से जुड़ी जानकारी को स्मार्ट तरीके से कैश मेमोरी में सेव कर पाता है. ऐसा इसलिए किया जाता है, ताकि जब आप इंटिग्रिटी के फ़ैसले का अनुरोध करें, तो मुख्य पाथ पर लेटेन्सी कम हो. टोकन उपलब्ध कराने वाली सेवा को फिर से तैयार करने से, इंटिग्रिटी की जांच कम बार की जा सकेगी. इससे, इंटिग्रिटी के अगले नतीजे को अपडेट करने में मदद मिलेगी.
आपको इंटिग्रिटी टोकन की सेवा देने वाली कंपनी को यह जानकारी देनी पड़ सकती है:
- जब आपका ऐप्लिकेशन लॉन्च होता है (यानी कि कोल्ड स्टार्ट अप पर). टोकन प्रोवाइडर को तैयार करने की प्रोसेस एसिंक्रोनस होती है. इसलिए, इससे स्टार्टअप टाइम पर कोई असर नहीं पड़ेगा. अगर आपको ऐप्लिकेशन लॉन्च होने के तुरंत बाद, सुरक्षा जांच के नतीजे का अनुरोध करना है, तो यह विकल्प बेहतर तरीके से काम करेगा. उदाहरण के लिए, जब कोई उपयोगकर्ता साइन इन करता है या कोई खिलाड़ी किसी गेम में शामिल होता है.
- जब आपका ऐप्लिकेशन खोला जाता है (यानी कि वॉर्म स्टार्ट अप पर). हालांकि, ध्यान दें कि हर ऐप्लिकेशन इंस्टेंस, हर मिनट में सिर्फ़ पांच बार इंटिग्रिटी टोकन जनरेट कर सकता है.
- बैकग्राउंड में किसी भी समय, जब आपको इंटिग्रिटी के फ़ैसले के अनुरोध से पहले टोकन तैयार करना हो.
इंटिग्रिटी टोकन देने वाली कंपनी को तैयार करने के लिए, यह तरीका अपनाएं:
- यहां दिए गए उदाहरणों में दिखाए गए तरीके से,
StandardIntegrityManager
बनाएं. PrepareIntegrityTokenRequest
बनाएं. इसके लिए,setCloudProjectNumber()
तरीके का इस्तेमाल करके Google Cloud प्रोजेक्ट नंबर डालें.- मैनेजर का इस्तेमाल करके
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));
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(); }
Unreal Engine
// .h void MyClass::OnPrepareIntegrityTokenCompleted( EStandardIntegrityErrorCode ErrorCode, UStandardIntegrityTokenProvider* Provider) { // Check the resulting error code. if (ErrorCode == EStandardIntegrityErrorCode::StandardIntegrity_NO_ERROR) { // ... } } // .cpp void MyClass::PrepareIntegrityToken() { int64 CloudProjectNumber = ... // Create the Integrity Token Request. FPrepareIntegrityTokenRequest Request = { CloudProjectNumber }; // Create a delegate to bind the callback function. FPrepareIntegrityOperationCompletedDelegate Delegate; // Bind the completion handler (OnPrepareIntegrityTokenCompleted) to the delegate. Delegate.BindDynamic(this, &MyClass::OnPrepareIntegrityTokenCompleted); // Initiate the prepare integrity token operation, passing the delegate to handle the result. GetGameInstance() ->GetSubsystem<UStandardIntegrityManager>() ->PrepareIntegrityToken(Request, Delegate); }
मूल भाषा वाला
/// 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
फ़ील्ड को इंटिग्रिटी टोकन में शामिल किया जाता है. इसलिए, लंबी वैल्यू से अनुरोध का साइज़ बढ़ सकता है. - डाइजेस्ट को Play Integrity API में
requestHash
फ़ील्ड के तौर पर उपलब्ध कराएं और इंटिग्रिटी टोकन पाएं.
इंटिग्रिटी की जांच का नतीजा मिलने पर:
- इंटीग्रिटी टोकन को डिकोड करें और
requestHash
फ़ील्ड को निकालें. - अनुरोध का डाइजेस्ट उसी तरीके से कंप्यूट करें जिस तरीके से ऐप्लिकेशन में किया जाता है. उदाहरण के लिए, अनुरोध के स्टेबल सीरियलाइज़ेशन का SHA256.
- ऐप्लिकेशन-साइड और सर्वर-साइड डाइजेस्ट की तुलना करें. अगर ये मेल नहीं खाते हैं, तो अनुरोध पर भरोसा नहीं किया जा सकता.
मांग पर इंटिग्रिटी की जांच के नतीजे का अनुरोध करना
इंटिग्रिटी टोकन उपलब्ध कराने की सुविधा सेट अप करने के बाद, Google Play से इंटिग्रिटी की जांच के नतीजे पाने का अनुरोध किया जा सकता है. इसके लिए, यह तरीका अपनाएं:
StandardIntegrityTokenProvider
पाएं.StandardIntegrityTokenRequest
बनाएं. इसमें, उपयोगकर्ता की उस कार्रवाई का अनुरोध हैश डालें जिसे आपकोsetRequestHash
तरीके से सुरक्षित करना है.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));
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(); }
Unreal Engine
// .h void MyClass::OnRequestIntegrityTokenCompleted( EStandardIntegrityErrorCode ErrorCode, UStandardIntegrityToken* Response) { // Check the resulting error code. if (ErrorCode == EStandardIntegrityErrorCode::StandardIntegrity_NO_ERROR) { // Get the token. FString Token = Response->Token; } } // .cpp void MyClass::RequestIntegrityToken() { UStandardIntegrityTokenProvider* Provider = ... // Prepare the UStandardIntegrityTokenProvider. // Request integrity token by providing a user action request hash. Can be called // several times for different user actions. FString RequestHash = ...; FStandardIntegrityTokenRequest Request = { RequestHash }; // Create a delegate to bind the callback function. FStandardIntegrityOperationCompletedDelegate Delegate; // Bind the completion handler (OnRequestIntegrityTokenCompleted) to the delegate. Delegate.BindDynamic(this, &MyClass::OnRequestIntegrityTokenCompleted); // Initiate the standard integrity token request, passing the delegate to handle the result. Provider->Request(Request, Delegate); }
मूल भाषा वाला
/// 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();
अगर आपका ऐप्लिकेशन लंबे समय तक एक ही टोकन प्रोवाइडर का इस्तेमाल करता है, तो टोकन प्रोवाइडर की समयसीमा खत्म हो सकती है. इससे अगले टोकन अनुरोध पर, INTEGRITY_TOKEN_PROVIDER_INVALID गड़बड़ी का मैसेज दिखता है. आपको इस गड़बड़ी को ठीक करने के लिए, नई कंपनी से अनुरोध करना चाहिए.
इंटिग्रिटी के नतीजे को डिक्रिप्ट करना और उसकी पुष्टि करना
पूरी सुरक्षा की जांच के नतीजे का अनुरोध करने के बाद, Play Integrity API एक एन्क्रिप्ट (सुरक्षित) किया गया रिस्पॉन्स टोकन उपलब्ध कराता है. डिवाइस इंटिग्रिटी के नतीजे पाने के लिए, आपको Google के सर्वर पर इंटिग्रिटी टोकन को डिक्रिप्ट करना होगा. इसके लिए, यह तरीका अपनाएं:
- अपने ऐप्लिकेशन से लिंक किए गए Google Cloud प्रोजेक्ट में, एक सेवा खाता बनाएं.
अपने ऐप्लिकेशन के सर्वर पर, playintegrity स्कोप का इस्तेमाल करके, अपने सेवा खाते के क्रेडेंशियल से ऐक्सेस टोकन फ़ेच करें. इसके बाद, यह अनुरोध करें:
playintegrity.googleapis.com/v1/PACKAGE_NAME:decodeIntegrityToken -d \ '{ "integrity_token": "INTEGRITY_TOKEN" }'
JSON फ़ॉर्मैट में मिले जवाब को पढ़ें.
इससे मिलने वाला पेलोड, सादे टेक्स्ट वाला एक टोकन होता है. इसमें integrity verdicts शामिल होते हैं.
ऑटोमैटिक रीप्ले प्रोटेक्शन
रिप्ले अटैक को कम करने के लिए, Google Play अपने-आप इंटिग्रिटी टोकन को कई बार इस्तेमाल होने से रोकता है. एक ही टोकन को बार-बार डिक्रिप्ट करने की कोशिश करने पर, फ़ैसले इस तरह से साफ़ तौर पर दिखेंगे:
- डिवाइस की पहचान करने से जुड़ा फ़ैसला खाली होगा.
- ऐप्लिकेशन की पहचान की पुष्टि और ऐप्लिकेशन के लिए लाइसेंस के नतीजे
UNEVALUATED
पर सेट हो जाएंगे. - Play Console का इस्तेमाल करके चालू किए गए किसी भी वैकल्पिक फ़ैसले को
UNEVALUATED
पर सेट कर दिया जाएगा. अगर यह एक से ज़्यादा वैल्यू वाला फ़ैसला है, तो इसे खाली फ़ैसले पर सेट कर दिया जाएगा.
Google Play प्रॉम्प्ट की मदद से, फ़ैसले से जुड़ी समस्याओं को ठीक करना (ज़रूरी नहीं)
आपके सर्वर को इंटिग्रिटी का नतीजा मिलने के बाद, वह यह तय कर सकता है कि आगे क्या करना है. अगर फ़ैसले से पता चलता है कि कोई समस्या है, जैसे कि ऐप्लिकेशन का लाइसेंस न होना, उसमें छेड़छाड़ होना या डिवाइस से समझौता किया गया हो, तो उपयोगकर्ताओं को समस्या ठीक करने का मौका दिया जा सकता है.
Play Integrity API, Google Play का एक डायलॉग बॉक्स दिखाने का विकल्प देता है. इससे उपयोगकर्ता को कार्रवाई करने के लिए कहा जाता है. उदाहरण के लिए, Google Play से आपके ऐप्लिकेशन का आधिकारिक वर्शन पाने के लिए.
सर्वर से मिले जवाब के आधार पर, अपने ऐप्लिकेशन में इन डायलॉग को ट्रिगर करने का तरीका जानने के लिए, समस्या हल करने वाले डायलॉग देखें.