Android, नेटवर्क पर सुरक्षित तरीके से जानकारी भेजने और पाने के लिए, सुरक्षा Provider
पर निर्भर करता है. हालांकि, समय-समय पर,
सुरक्षा से जुड़े जोखिम, डिफ़ॉल्ट सुरक्षा सेवा देने वाली कंपनी में पाए जाते हैं. बचाव के लिए
इन जोखिमों को जानना होगा, Google Play
सेवाएं किसी डिवाइस के सुरक्षा देने वाले को अपने आप अपडेट करने का तरीका देती हैं
जाने-पहचाने नुकसान से बचाने के लिए. Google Play services के तरीकों को कॉल करके, यह पक्का किया जा सकता है कि आपका ऐप्लिकेशन ऐसे डिवाइस पर चल रहा है जिसमें हाल ही के अपडेट हैं. इससे, ऐप्लिकेशन को पहले से मौजूद एक्सप्लॉइट से बचाया जा सकता है.
उदाहरण के लिए, OpenSSL में जोखिम की आशंका का पता चला (CVE-2014-0224) जिसकी वजह से ऐप्लिकेशन पर, पाथ पर हमला होने की वजह से, आपके ऐप्लिकेशन को डिक्रिप्ट किया जा सकता है. को सुरक्षित रखा जा सकता है. Google Play services का वर्शन 5.0 में समस्या को हल किया जा सकता है, लेकिन ऐप्लिकेशन के लिए यह जांच करना ज़रूरी है कि यह सुधार इंस्टॉल किया गया है या नहीं. Google Play services के तरीकों का इस्तेमाल करके, यह पक्का किया जा सकता है कि आपका ऐप्लिकेशन ऐसे डिवाइस पर चल रहा है जो इस तरह के हमले से सुरक्षित है.
चेतावनी: डिवाइस की सुरक्षा अपडेट करना
Provider
अपडेट नहीं होता
android.net.SSLCertificateSocketFactory
,
जो जोखिम में बना रहता है. इस रुकी हुई क्लास का इस्तेमाल करने के बजाय, हम ऐप्लिकेशन डेवलपर को सलाह देते हैं कि वे
क्रिप्टोग्राफ़ी के साथ इंटरैक्ट करने के लिए, हाई-लेवल तरीकों का इस्तेमाल करें. जैसे
HttpsURLConnection
.
ProviderInstaller का इस्तेमाल करके, सुरक्षा सेवा देने वाली कंपनी को पैच करना
किसी डिवाइस के लिए सुरक्षा सेवा देने वाली कंपनी की जानकारी अपडेट करने के लिए, ProviderInstaller
क्लास का इस्तेमाल करें. आप पुष्टि कर सकते हैं कि सुरक्षा देने वाली कंपनी अप-टू-डेट है. साथ ही, उसे अपडेट भी कर सकती है,
(अगर ज़रूरी हो) पर कॉल करें
यह क्लास installIfNeeded()
है
(या installIfNeededAsync()
)
तरीका. इस सेक्शन में, इन विकल्पों के बारे में खास जानकारी दी गई है. इसके बाद आने वाले सेक्शन में
ज़्यादा जानकारी वाले चरण और उदाहरण देखें.
installIfNeeded()
को कॉल करने पर, ProviderInstaller
ये काम करता है:
- डिवाइस का
Provider
सही से काम करने पर अपडेट किया गया (या पहले से अप-टू-डेट है) है, तो तरीका बिना किसी अपवाद के वापस आ जाता है. - अगर डिवाइस की Google Play services लाइब्रेरी पुरानी है, तो
थ्रो
GooglePlayServicesRepairableException
. इसके बाद, ऐप्लिकेशन इस अपवाद को पकड़ सकता है और उपयोगकर्ता को Google Play services को अपडेट करने के लिए सही डायलॉग बॉक्स दिखा सकता है. - अगर कोई ऐसी गड़बड़ी होती है जिसे ठीक नहीं किया जा सकता, तो यह तरीका
Provider
को अपडेट नहीं कर पाता. इसकी जानकारी देने के लिए, यह तरीकाGooglePlayServicesNotAvailableException
को दिखाता है. इसके बाद, ऐप्लिकेशन अपवाद को पकड़ सकता है और कोई सही कार्रवाई चुन सकता है. जैसे, स्टैंडर्ड इसे ठीक करने का फ़्लो डायग्राम दिखाना.
installIfNeededAsync()
वाला तरीका भी इसी तरह काम करता है. हालांकि, अपवाद दिखाने के बजाय, यह काम पूरा होने या न होने के बारे में बताने के लिए, सही कॉलबैक तरीके को कॉल करता है.
अगर सुरक्षा सेवा देने वाली कंपनी पहले से ही अप-टू-डेट है, तो installIfNeeded()
को बहुत कम समय लगता है. अगर इस तरीके से, नया Provider
इंस्टॉल करना ज़रूरी है, तो इसमें 30 से 50 मिलीसेकंड (नए डिवाइसों पर) से लेकर 350 मिलीसेकंड (पुराने डिवाइसों पर) तक लग सकते हैं. उपयोगकर्ता अनुभव पर असर न पड़े, इसके लिए:
- थ्रेड लोड होने के बाद, बैकग्राउंड नेटवर्किंग थ्रेड से तुरंत
installIfNeeded()
को कॉल करें. ऐसा करने से, थ्रेड के नेटवर्क का इस्तेमाल करने की कोशिश करने का इंतज़ार नहीं करना पड़ता. (इस तरीके को कई बार कॉल करने से कोई नुकसान नहीं होता, क्योंकि अगर सुरक्षा सेवा देने वाली कंपनी को अपडेट करने की ज़रूरत नहीं है, तो यह तुरंत रिटर्न हो जाता है.) - एसिंक्रोनस को कॉल करें
अलग-अलग वर्शन का इस्तेमाल करके,
installIfNeededAsync()
, अगर थ्रेड की वजह से उपयोगकर्ता अनुभव पर असर पड़ सकता है ब्लॉक करना—उदाहरण के लिए, अगर कॉल यूज़र इंटरफ़ेस (यूआई) थ्रेड में किसी गतिविधि से आया है. (अगर ऐसा किया जाता है, तो आपको सुरक्षित तरीके से कोई भी कम्यूनिकेशन करने से पहले, ऑपरेशन के पूरा होने का इंतज़ार करना होगा. कॉन्टेंट बनानेProviderInstaller
अभी तक किसी भी व्यक्ति ने चेक इन नहीं किया है आपके लिसनर केonProviderInstalled()
को कॉल करता है मदद मिलती है.)
चेतावनी: अगर
ProviderInstaller
अपडेट किए गए Provider
को इंस्टॉल करने में असमर्थ
आपके डिवाइस की सुरक्षा करने वाली कंपनी के किसी भी नुकसान का जोखिम हो सकता है. आपका ऐप्लिकेशन
इस तरह से काम करना चाहिए जैसे कि सभी एचटीटीपी कम्यूनिकेशन सुरक्षित न हों.
Provider
अपडेट होने के बाद, सुरक्षा एपीआई (एसएसएल एपीआई के साथ) के सभी कॉल को इसके ज़रिए रूट किया जाता है.
हालांकि, यह android.net.SSLCertificateSocketFactory
पर लागू नहीं होता. यह CVE-2014-0224 जैसे खतरों से सुरक्षित नहीं है.
एक साथ पैच करना
सुरक्षा देने वाली कंपनी को पैच करने का सबसे आसान तरीका है, सिंक्रोनस को कॉल करना
तरीका installIfNeeded()
.
यह तब सही होता है, जब कार्रवाई पूरी होने का इंतज़ार करने के दौरान, थ्रेड को ब्लॉक करने से उपयोगकर्ता अनुभव पर असर न पड़े.
उदाहरण के लिए, यहां एक वर्कर को लागू करने का तरीका बताया गया है, जो सुरक्षा सेवा देने वाली कंपनी को अपडेट करता है. कर्मचारी होने के बाद से
बैकग्राउंड में चलता है, अगर इंतज़ार करते समय थ्रेड ब्लॉक हो जाता है, तो कोई समस्या नहीं है
अपडेट किया जा सकता है. कर्मचारी, सुरक्षा सेवा देने वाली कंपनी को अपडेट करने के लिए installIfNeeded()
को कॉल करता है. अगर यह तरीका सामान्य रूप से काम करता है, तो वर्कफ़्लो को पता चलता है कि सुरक्षा सेवा देने वाली कंपनी का वर्शन अप-टू-डेट है. अगर इस तरीके में कोई अपवाद दिखता है,
काम करने वाला व्यक्ति उचित कार्रवाई कर सकता है (जैसे कि उपयोगकर्ता से
Google Play services अपडेट करने के लिए.
Kotlin
/** * Sample patch Worker using {@link ProviderInstaller}. */ class PatchWorker(appContext: Context, workerParams: WorkerParameters): Worker(appContext, workerParams) { override fun doWork(): Result { try { ProviderInstaller.installIfNeeded(context) } catch (e: GooglePlayServicesRepairableException) { // Indicates that Google Play services is out of date, disabled, etc. // Prompt the user to install/update/enable Google Play services. GoogleApiAvailability.getInstance() .showErrorNotification(context, e.connectionStatusCode) // Notify the WorkManager that a soft error occurred. return Result.failure() } catch (e: GooglePlayServicesNotAvailableException) { // Indicates a non-recoverable error; the ProviderInstaller can't // install an up-to-date Provider. // Notify the WorkManager that a hard error occurred. return Result.failure() } // If this is reached, you know that the provider was already up to date // or was successfully updated. return Result.success() } }
Java
/** * Sample patch Worker using {@link ProviderInstaller}. */ public class PatchWorker extends Worker { ... @Override public Result doWork() { try { ProviderInstaller.installIfNeeded(getContext()); } catch (GooglePlayServicesRepairableException e) { // Indicates that Google Play services is out of date, disabled, etc. // Prompt the user to install/update/enable Google Play services. GoogleApiAvailability.getInstance() .showErrorNotification(context, e.connectionStatusCode) // Notify the WorkManager that a soft error occurred. return Result.failure(); } catch (GooglePlayServicesNotAvailableException e) { // Indicates a non-recoverable error; the ProviderInstaller can't // install an up-to-date Provider. // Notify the WorkManager that a hard error occurred. return Result.failure(); } // If this is reached, you know that the provider was already up to date // or was successfully updated. return Result.success(); } }
एसिंक्रोनस रूप से पैच करें
सुरक्षा सेवा देने वाली कंपनी को अपडेट करने में, पुराने डिवाइसों पर 350 मिलीसेकंड लग सकते हैं. अगर किसी ऐसी थ्रेड पर अपडेट किया जा रहा है जिसका सीधा असर उपयोगकर्ता अनुभव पर पड़ता है, जैसे कि यूज़र इंटरफ़ेस (यूआई) थ्रेड, तो आपको प्रोवाइडर को अपडेट करने के लिए सिंक्रोनस कॉल नहीं करना चाहिए. ऐसा करने से, ऐप्लिकेशन या डिवाइस तब तक फ़्रीज़ हो सकता है, जब तक ऑपरेशन पूरा नहीं हो जाता. इसके बजाय, एक साथ कई काम करने वाले installIfNeededAsync()
तरीके का इस्तेमाल करें. वह तरीका कॉल करके इसके सफल या असफल होने का संकेत देता है
कॉलबैक.
उदाहरण के लिए, यहां कुछ कोड दिया गया है, जो सुरक्षा देने वाले को
गतिविधि देखी जा सकती है. गतिविधि के लिए installIfNeededAsync()
को कॉल किया गया
को अपडेट करता है और सफलता पाने के लिए खुद को लिसनर के तौर पर चुनता है
या विफलता की सूचना मिलेगी. अगर सुरक्षा सेवा देने वाली कंपनी का वर्शन अप-टू-डेट है या उसे अपडेट कर दिया गया है, तो गतिविधि के onProviderInstalled()
तरीके को कॉल किया जाता है. साथ ही, गतिविधि को यह पता चल जाता है कि डेटा सुरक्षित है. अगर सेवा देने वाली कंपनी को अपडेट नहीं किया जा सकता, तो गतिविधि के onProviderInstallFailed()
तरीके को कॉल किया जाता है. इसके बाद, गतिविधि ज़रूरी कार्रवाई कर सकती है. जैसे, उपयोगकर्ता को Google Play services अपडेट करने के लिए कहना.
Kotlin
private const val ERROR_DIALOG_REQUEST_CODE = 1 /** * Sample activity using {@link ProviderInstaller}. */ class MainActivity : Activity(), ProviderInstaller.ProviderInstallListener { private var retryProviderInstall: Boolean = false // Update the security provider when the activity is created. override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) ProviderInstaller.installIfNeededAsync(this, this) } /** * This method is only called if the provider is successfully updated * (or is already up to date). */ override fun onProviderInstalled() { // Provider is up to date; app can make secure network calls. } /** * This method is called if updating fails. The error code indicates * whether the error is recoverable. */ override fun onProviderInstallFailed(errorCode: Int, recoveryIntent: Intent) { GoogleApiAvailability.getInstance().apply { if (isUserResolvableError(errorCode)) { // Recoverable error. Show a dialog prompting the user to // install/update/enable Google Play services. showErrorDialogFragment(this@MainActivity, errorCode, ERROR_DIALOG_REQUEST_CODE) { // The user chose not to take the recovery action. onProviderInstallerNotAvailable() } } else { onProviderInstallerNotAvailable() } } } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == ERROR_DIALOG_REQUEST_CODE) { // Adding a fragment via GoogleApiAvailability.showErrorDialogFragment // before the instance state is restored throws an error. So instead, // set a flag here, which causes the fragment to delay until // onPostResume. retryProviderInstall = true } } /** * On resume, check whether a flag indicates that the provider needs to be * reinstalled. */ override fun onPostResume() { super.onPostResume() if (retryProviderInstall) { // It's safe to retry installation. ProviderInstaller.installIfNeededAsync(this, this) } retryProviderInstall = false } private fun onProviderInstallerNotAvailable() { // This is reached if the provider can't be updated for some reason. // App should consider all HTTP communication to be vulnerable and take // appropriate action. } }
Java
/** * Sample activity using {@link ProviderInstaller}. */ public class MainActivity extends Activity implements ProviderInstaller.ProviderInstallListener { private static final int ERROR_DIALOG_REQUEST_CODE = 1; private boolean retryProviderInstall; // Update the security provider when the activity is created. @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ProviderInstaller.installIfNeededAsync(this, this); } /** * This method is only called if the provider is successfully updated * (or is already up to date). */ @Override protected void onProviderInstalled() { // Provider is up to date; app can make secure network calls. } /** * This method is called if updating fails. The error code indicates * whether the error is recoverable. */ @Override protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) { GoogleApiAvailability availability = GoogleApiAvailability.getInstance(); if (availability.isUserRecoverableError(errorCode)) { // Recoverable error. Show a dialog prompting the user to // install/update/enable Google Play services. availability.showErrorDialogFragment( this, errorCode, ERROR_DIALOG_REQUEST_CODE, new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialog) { // The user chose not to take the recovery action. onProviderInstallerNotAvailable(); } }); } else { // Google Play services isn't available. onProviderInstallerNotAvailable(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == ERROR_DIALOG_REQUEST_CODE) { // Adding a fragment via GoogleApiAvailability.showErrorDialogFragment // before the instance state is restored throws an error. So instead, // set a flag here, which causes the fragment to delay until // onPostResume. retryProviderInstall = true; } } /** * On resume, check whether a flag indicates that the provider needs to be * reinstalled. */ @Override protected void onPostResume() { super.onPostResume(); if (retryProviderInstall) { // It's safe to retry installation. ProviderInstaller.installIfNeededAsync(this, this); } retryProviderInstall = false; } private void onProviderInstallerNotAvailable() { // This is reached if the provider can't be updated for some reason. // App should consider all HTTP communication to be vulnerable and take // appropriate action. } }