এই পৃষ্ঠায় ইন্টিগ্রিটি ফলাফলের জন্য স্ট্যান্ডার্ড API অনুরোধ করার পদ্ধতি বর্ণনা করা হয়েছে, যা Android 5.0 (API লেভেল ২১) বা তার পরবর্তী ভার্সনে কাজ করে। ইন্টার্যাকশনটি আসল কিনা তা চেক করার জন্য আপনার অ্যাপ যখনই সার্ভার কল করে, তখনই আপনি ইন্টিগ্রিটি ফলাফলের জন্য স্ট্যান্ডার্ড API অনুরোধ করতে পারেন।
এক নজরে
একটি স্ট্যান্ডার্ড অনুরোধের দুটি অংশ থাকে:
- ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করুন (একবার): ইন্টিগ্রিটি ফলাফল পাওয়ার আগে ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করতে আপনাকে Integrity API কল করতে হবে। যেমন, আপনার অ্যাপ লঞ্চ করার সময় বা ইন্টিগ্রিটি ফলাফল প্রয়োজন হওয়ার আগে ব্যাকগ্রাউন্ডে এটি করতে পারেন।
- ইন্টিগ্রিটি টোকেনের অনুরোধ করা (চাহিদা অনুযায়ী): আপনার অ্যাপ যখনই কোনও সার্ভার অনুরোধ করে যা আপনি আসল কিনা তা চেক করতে চান, আপনি একটি ইন্টিগ্রিটি টোকেনের অনুরোধ করেন এবং ডিক্রিপশন এবং যাচাইকরণের জন্য এটি আপনার অ্যাপের ব্যাকএন্ড সার্ভারে পাঠান। তারপর আপনার ব্যাকএন্ড সার্ভার নির্ধারণ করতে পারবে যে কীভাবে কাজ করতে হবে।
ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করুন (একবার):
- আপনার অ্যাপ আপনার Google Cloud প্রোজেক্ট নম্বরের মাধ্যমে ইন্টিগ্রিটি টোকেন প্রদানকারীকে কল করে।
- আরও অ্যাটেস্টেশন চেক কলের জন্য আপনার অ্যাপ মেমরিতে ইন্টিগ্রিটি টোকেন প্রদানকারীকে ধরে রাখে।
ইন্টিগ্রিটি টোকেনের জন্য অনুরোধ করুন (চাহিদা অনুযায়ী):
- ব্যবহারকারীর যে অ্যাকশন সুরক্ষিত করা প্রয়োজন, আপনার অ্যাপ সেই অনুরোধের হ্যাশ (SHA256-এর মতো উপযুক্ত হ্যাশ অ্যালগরিদম ব্যবহার করে) গণনা করে।
- আপনার অ্যাপ ইন্টিগ্রিটি টোকেনের জন্য অনুরোধ করে, অনুরোধের হ্যাশ পাস করে।
- আপনার অ্যাপ Play Integrity API থেকে স্বাক্ষরিত ও এনক্রিপ্ট করা ইন্টিগ্রিটি টোকেন পায়।
- আপনার অ্যাপ, অ্যাপের ব্যাকএন্ডে ইন্টিগ্রিটি টোকেন পাস করে।
- আপনার অ্যাপের ব্যাকএন্ড Google Play সার্ভারে টোকেন পাঠায়। Google Play সার্ভার রায় ডিক্রিপ্ট ও যাচাই করে, আপনার অ্যাপের ব্যাকএন্ডে ফলাফল ফেরত পাঠায়।
- টোকেন পেলোডে থাকা সিগন্যালের উপর ভিত্তি করে আপনার অ্যাপের ব্যাকএন্ড নির্ধারণ করে যে কীভাবে এগোতে হবে।
- আপনার অ্যাপের ব্যাকএন্ড আপনার অ্যাপে সিদ্ধান্তের ফলাফল পাঠায়।
ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করুন (একবার)
Google Play থেকে ইন্টিগ্রিটি ফলাফলের জন্য স্ট্যান্ডার্ড অনুরোধ করার আগে, আপনাকে ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত (বা "ওয়ার্ম আপ") করতে হবে। এটি Google Play-কে ডিভাইসে আংশিক অ্যাটেস্টেশন তথ্য স্মার্টভাবে ক্যাশে করার অনুমতি দেয় যাতে আপনি ইন্টিগ্রিটি ফলাফলের জন্য অনুরোধ করার সময় ক্রিটিক্যাল পাথে লেটেন্সি কমানো যায়। টোকেন প্রোভাইডার আবার প্রস্তুত করার অর্থ হল কম রিসোর্স-ভারী ইন্টিগ্রিটি চেক পুনরাবৃত্তি করা, যার ফলে আপনার অনুরোধ করা পরবর্তী ইন্টিগ্রিটি ফলাফল আরও আপ-টু-ডেট হবে।
আপনি ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করতে পারেন:
- আপনার অ্যাপ চালু হওয়ার সময় (যেমন, কোল্ড স্টার্ট আপের সময়)। টোকেন প্রোভাইডার প্রস্তুত করা অ্যাসিঙ্ক্রোনাস এবং তাই স্টার্ট আপের সময়কে প্রভাবিত করবে না। অ্যাপ লঞ্চ করার কিছুক্ষণ পরেই ইন্টিগ্রিটি ফলাফল সংক্রান্ত অনুরোধ করার পরিকল্পনা থাকলে, এই বিকল্পটি ভালোভাবে কাজ করবে, যেমন কোনও ব্যবহারকারী সাইন-ইন করলে বা কোনও প্লেয়ার গেমে যোগ দিলে।
- আপনার অ্যাপ খোলা হলে (যেমন, ওয়ার্ম স্টার্ট আপে)। তবে, মনে রাখবেন যে প্রতিটি অ্যাপ ইনস্ট্যান্স প্রতি মিনিটে সর্বাধিক ৫ বার ইন্টিগ্রিটি টোকেন প্রস্তুত করতে পারে।
- ইন্টিগ্রিটি ফলাফল সংক্রান্ত অনুরোধের আগে ব্যাকগ্রাউন্ডে যেকোনও সময় আপনি টোকেন প্রস্তুত করতে চাইলে।
ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করতে, নিম্নলিখিত ধাপগুলি অনুসরণ করুন:
- নিচের উদাহরণে যেভাবে দেখানো হয়েছে, সেইভাবে একটি
StandardIntegrityManagerতৈরি করুন। PrepareIntegrityTokenRequestতৈরি করুন,setCloudProjectNumber()পদ্ধতির মাধ্যমে Google Cloud প্রোজেক্ট নম্বর প্রদান করুন।prepareIntegrityToken()-কে কল করার জন্য ম্যানেজার ব্যবহার করুন,PrepareIntegrityTokenRequestপ্রদান করুন।
জাভা
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 = ...; // Initialize the V2 manager. Requires Play Integrity Unity Plugin v2.0.0 // or higher. var standardIntegrityManager = new StandardIntegrityManagerV2(); // 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 != null && integrityTokenProviderOperation.Error.ErrorCode != StandardIntegrityErrorCode.NoError) { AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " + integrityTokenProviderOperation.Error.ErrorCode); 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ফিল্ডে সেট করা ভ্যালুর সর্বাধিক দৈর্ঘ্য ৫০০ বাইট।requestHash-এ যেকোনও অ্যাপ অনুরোধ ডেটা অন্তর্ভুক্ত করুন যা আপনি চেক বা সুরক্ষিত করছেন এমন অ্যাকশনের জন্য গুরুত্বপূর্ণ বা প্রাসঙ্গিক।requestHashফিল্ডটি ইন্টিগ্রিটি টোকেনে হুবহু অন্তর্ভুক্ত করা হয়, তাই দীর্ঘ মান অনুরোধের সাইজ বাড়াতে পারে। - Play Integrity API-তে
requestHashফিল্ড হিসেবে ডাইজেস্ট প্রদান করুন এবং ইন্টিগ্রিটি টোকেন পান।
আপনি ইন্টিগ্রিটি ফলাফল পেলে:
- ইন্টিগ্রিটি টোকেন ডিকোড করুন এবং
requestHashফিল্ড এক্সট্র্যাক্ট করুন। - অ্যাপে যেভাবে করা হয় ঠিক সেইভাবে অনুরোধের ডাইজেস্ট গণনা করুন (যেমন, স্টেবল অনুরোধ সিরিয়ালাইজেশনের SHA256)।
- অ্যাপ-সাইড ও সার্ভার-সাইড ডাইজেস্টের তুলনা করুন। যদি সেগুলি না মেলে, তাহলে অনুরোধটি বিশ্বাসযোগ্য নয়।
ইন্টিগ্রিটি ফলাফলের জন্য অনুরোধ করা (চাহিদা অনুযায়ী)
ইন্টিগ্রিটি টোকেন প্রোভাইডার প্রস্তুত করার পরে, আপনি Google Play থেকে ইন্টিগ্রিটি ফলাফল অনুরোধ করা শুরু করতে পারবেন। এটি করতে, নিম্নলিখিত ধাপগুলি সম্পূর্ণ করুন:
StandardIntegrityTokenProviderসংগ্রহ করুন।StandardIntegrityTokenRequestতৈরি করুন,setRequestHashপদ্ধতির মাধ্যমে আপনি যে ব্যবহারকারীর অ্যাকশন সুরক্ষিত করতে চান তার অনুরোধের হ্যাশ প্রদান করুন।request()কল করতে ইন্টিগ্রিটি টোকেন প্রোভাইডার ব্যবহার করুন,StandardIntegrityTokenRequestপ্রদান করুন।
জাভা
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() { StandardIntegrityManagerV2.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 != null && integrityTokenOperation.Error.ErrorCode != StandardIntegrityErrorCode.NoError) { AppendStatusLog("StandardIntegrityAsyncOperation failed with error: " + integrityTokenOperation.Error.ErrorCode); 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 রেসপন্স পড়ুন।
এর ফলে যে পেলোড পাওয়া যায় তা হল প্লেন-টেক্সট টোকেন যাতে ইন্টিগ্রিটি ফলাফল থাকে।
অটোমেটিক রিপ্লে সুরক্ষা
রিপ্লে অ্যাটাক কমাতে, Google Play অটোমেটিক ইন্টিগ্রিটি টোকেন একাধিকবার ব্যবহার করা থেকে আটকায়। একই টোকেন বারবার ডিক্রিপ্ট করার চেষ্টা করলে, নিম্নলিখিত উপায়ে রায় মুছে দেওয়া হবে:
- ডিভাইস শনাক্তকরণ সংক্রান্ত রায় খালি থাকবে।
- অ্যাপ শনাক্তকরণ সংক্রান্ত রায় এবং অ্যাপ লাইসেন্সিং সংক্রান্ত রায়
UNEVALUATED-এ সেট করা হবে। - Play Console ব্যবহার করে চালু করা যেকোনও ঐচ্ছিক রায়
UNEVALUATED-এ সেট করা হবে (অথবা এটি মাল্টি-ভ্যালু রায় হলে খালি রায় হিসেবে সেট করা হবে)।
Google Play প্রম্পটের মাধ্যমে রায় সংক্রান্ত সমস্যার সমাধান করা (ঐচ্ছিক)
আপনার সার্ভার ইন্টিগ্রিটি ফলাফল পাওয়ার পরে, এটি কীভাবে এগোতে হবে তা নির্ধারণ করতে পারে। রায় যদি কোনও সমস্যা নির্দেশ করে—যেমন অ্যাপটি লাইসেন্সবিহীন, টেম্পার করা হয়েছে বা ডিভাইসটি কম্প্রোমাইজ করা হয়েছে—আপনি ব্যবহারকারীদের সমস্যাটি নিজেরাই সমাধান করার সুযোগ দিতে পারেন।
Play Integrity API-তে Google Play ডায়ালগ দেখানোর বিকল্প আছে যা ব্যবহারকারীকে অ্যাকশন নিতে প্রম্পট করে, যেমন, Google Play থেকে আপনার অ্যাপের অফিসিয়াল ভার্সন পাওয়া।
সার্ভারের উত্তরের ভিত্তিতে আপনার অ্যাপ থেকে কীভাবে এইসব ডায়ালগ ট্রিগার করবেন তা জানতে, প্রতিকার ডায়ালগ দেখুন।