अपने ऐप्लिकेशन को ज़्यादा सुरक्षित बनाकर, लोगों का भरोसा बनाए रखने और डिवाइस की इंटिग्रिटी को सुरक्षित रखने में मदद मिलती है.
इस पेज पर, कई सबसे सही तरीके बताए गए हैं. इनसे आपके ऐप्लिकेशन की सुरक्षा पर काफ़ी अच्छा असर पड़ता है.
सुरक्षित कम्यूनिकेशन लागू करना
अपने ऐप्लिकेशन और अन्य ऐप्लिकेशन के बीच या अपने ऐप्लिकेशन और किसी वेबसाइट के बीच शेयर किए जाने वाले डेटा को सुरक्षित रखने से, आपके ऐप्लिकेशन की परफ़ॉर्मेंस बेहतर होती है. साथ ही, भेजे और पाए जाने वाले डेटा को सुरक्षित रखा जा सकता है.
ऐप्लिकेशन के बीच होने वाले कम्यूनिकेशन को सुरक्षित रखना
ऐप्लिकेशन के बीच ज़्यादा सुरक्षित तरीके से कम्यूनिकेट करने के लिए, ऐप्लिकेशन चुनने की सुविधा, हस्ताक्षर पर आधारित अनुमतियां, और एक्सपोर्ट न किए गए कॉन्टेंट उपलब्ध कराने वाली कंपनियों के साथ इंप्लिसिट इंटेंट का इस्तेमाल करें.
ऐप्लिकेशन चुनने की सुविधा दिखाना
अगर किसी इंप्लिसिट इंटेंट से, उपयोगकर्ता के डिवाइस पर कम से कम दो ऐप्लिकेशन लॉन्च किए जा सकते हैं, तो ऐप्लिकेशन चुनने का विकल्प साफ़ तौर पर दिखाएं. इस इंटरैक्शन रणनीति की मदद से, उपयोगकर्ता अपनी संवेदनशील जानकारी को किसी ऐसे ऐप्लिकेशन पर ट्रांसफ़र कर सकते हैं जिस पर वे भरोसा करते हैं.
Kotlin
val intent = Intent(Intent.ACTION_SEND) val possibleActivitiesList: List<ResolveInfo> = packageManager.queryIntentActivities(intent, PackageManager.MATCH_ALL) // Verify that an activity in at least two apps on the user's device // can handle the intent. Otherwise, start the intent only if an app // on the user's device can handle the intent. if (possibleActivitiesList.size > 1) { // Create intent to show chooser. // Title is something similar to "Share this photo with." val chooser = resources.getString(R.string.chooser_title).let { title -> Intent.createChooser(intent, title) } startActivity(chooser) } else if (intent.resolveActivity(packageManager) != null) { startActivity(intent) }
Java
Intent intent = new Intent(Intent.ACTION_SEND); List<ResolveInfo> possibleActivitiesList = getPackageManager() .queryIntentActivities(intent, PackageManager.MATCH_ALL); // Verify that an activity in at least two apps on the user's device // can handle the intent. Otherwise, start the intent only if an app // on the user's device can handle the intent. if (possibleActivitiesList.size() > 1) { // Create intent to show chooser. // Title is something similar to "Share this photo with." String title = getResources().getString(R.string.chooser_title); Intent chooser = Intent.createChooser(intent, title); startActivity(chooser); } else if (intent.resolveActivity(getPackageManager()) != null) { startActivity(intent); }
इसी विषय से जुड़ी जानकारी:
हस्ताक्षर के आधार पर अनुमतियां लागू करना
आपके कंट्रोल या मालिकाना हक वाले दो ऐप्लिकेशन के बीच डेटा शेयर करते समय, हस्ताक्षर पर आधारित अनुमतियों का इस्तेमाल करें. इन अनुमतियों के लिए, उपयोगकर्ता की पुष्टि की ज़रूरत नहीं होती. इसके बजाय, यह जांच की जाती है कि डेटा ऐक्सेस करने वाले ऐप्लिकेशन, एक ही हस्ताक्षर करने वाली कुंजी का इस्तेमाल करके साइन किए गए हैं. इसलिए, इन अनुमतियों से उपयोगकर्ताओं को बेहतर और सुरक्षित अनुभव मिलता है.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <permission android:name="my_custom_permission_name" android:protectionLevel="signature" />
इसी विषय से जुड़ी जानकारी:
अपने ऐप्लिकेशन के कॉन्टेंट प्रोवाइडर का ऐक्सेस न दें
अगर आपको अपने ऐप्लिकेशन का डेटा किसी ऐसे ऐप्लिकेशन को नहीं भेजना है जिसका मालिकाना हक आपके पास नहीं है, तो अन्य डेवलपर के ऐप्लिकेशन को अपने ऐप्लिकेशन के ContentProvider
ऑब्जेक्ट ऐक्सेस करने की अनुमति न दें. अगर आपका ऐप्लिकेशन, Android 4.1.1 (एपीआई लेवल 16) या इससे पुराने वर्शन वाले डिवाइसों पर इंस्टॉल किया जा सकता है, तो यह सेटिंग खास तौर पर ज़रूरी है. ऐसा इसलिए, क्योंकि Android के इन वर्शन पर, <provider>
एलिमेंट के android:exported
एट्रिब्यूट की वैल्यू डिफ़ॉल्ट रूप से true
होती है.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp"> <application ... > <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.example.myapp.fileprovider" ... android:exported="false"> <!-- Place child elements of <provider> here. --> </provider> ... </application> </manifest>
संवेदनशील जानकारी दिखाने से पहले क्रेडेंशियल मांगना
जब उपयोगकर्ताओं से क्रेडेंशियल का अनुरोध किया जाता है, ताकि वे आपके ऐप्लिकेशन में संवेदनशील जानकारी या प्रीमियम कॉन्टेंट को ऐक्सेस कर सकें, तो उनसे पिन/पासवर्ड/पैटर्न या बायोमेट्रिक क्रेडेंशियल (जैसे, चेहरे की पहचान या फ़िंगरप्रिंट की पहचान) में से किसी एक के लिए कहें.
बायोमेट्रिक क्रेडेंशियल का अनुरोध करने के तरीके के बारे में ज़्यादा जानने के लिए, बायोमेट्रिक पुष्टि के बारे में गाइड देखें.
नेटवर्क सुरक्षा के उपाय लागू करना
यहां दिए गए सेक्शन में बताया गया है कि अपने ऐप्लिकेशन के नेटवर्क की सुरक्षा को कैसे बेहतर बनाया जा सकता है.
टीएलएस ट्रैफ़िक का इस्तेमाल करना
अगर आपका ऐप्लिकेशन किसी ऐसे वेब सर्वर से कम्यूनिकेट करता है जिसके पास किसी जानी-मानी और भरोसेमंद सर्टिफ़िकेट देने वाली संस्था (सीए) से जारी किया गया सर्टिफ़िकेट है, तो एचटीटीपीएस अनुरोध का इस्तेमाल करें. जैसे:
Kotlin
val url = URL("https://www.google.com") val urlConnection = url.openConnection() as HttpsURLConnection urlConnection.connect() urlConnection.inputStream.use { ... }
Java
URL url = new URL("https://www.google.com"); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.connect(); InputStream in = urlConnection.getInputStream();
नेटवर्क सुरक्षा कॉन्फ़िगरेशन जोड़ना
अगर आपका ऐप्लिकेशन नए या कस्टम सीए का इस्तेमाल करता है, तो कॉन्फ़िगरेशन फ़ाइल में अपने नेटवर्क की सुरक्षा सेटिंग के बारे में बताया जा सकता है. इस प्रोसेस की मदद से, ऐप्लिकेशन के कोड में बदलाव किए बिना कॉन्फ़िगरेशन बनाया जा सकता है.
अपने ऐप्लिकेशन में नेटवर्क सुरक्षा कॉन्फ़िगरेशन फ़ाइल जोड़ने के लिए, यह तरीका अपनाएं:
- अपने ऐप्लिकेशन की मेनिफ़ेस्ट फ़ाइल में कॉन्फ़िगरेशन का एलान करें:
-
res/xml/network_security_config.xml
में मौजूद एक्सएमएल रिसॉर्स फ़ाइल जोड़ें.यह तय करें कि कुछ खास डोमेन पर आने वाले सभी ट्रैफ़िक के लिए एचटीटीपीएस का इस्तेमाल किया जाना चाहिए. इसके लिए, साफ़ तौर पर लिखे गए टेक्स्ट को बंद करें:
<network-security-config> <domain-config cleartextTrafficPermitted="false"> <domain includeSubdomains="true">secure.example.com</domain> ... </domain-config> </network-security-config>
डेवलपमेंट प्रोसेस के दौरान,
<debug-overrides>
एलिमेंट का इस्तेमाल करके, उपयोगकर्ता के इंस्टॉल किए गए सर्टिफ़िकेट को साफ़ तौर पर अनुमति दी जा सकती है. यह एलिमेंट, डीबग करने और जांच करने के दौरान, आपके ऐप्लिकेशन के सुरक्षा से जुड़े अहम विकल्पों को बदल देता है. हालांकि, इससे ऐप्लिकेशन के रिलीज़ कॉन्फ़िगरेशन पर कोई असर नहीं पड़ता. यहां दिए गए स्निपेट में, आपके ऐप्लिकेशन की नेटवर्क सुरक्षा कॉन्फ़िगरेशन वाली एक्सएमएल फ़ाइल में इस एलिमेंट को तय करने का तरीका बताया गया है:<network-security-config> <debug-overrides> <trust-anchors> <certificates src="user" /> </trust-anchors> </debug-overrides> </network-security-config>
<manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > <!-- Place child elements of <application> element here. --> </application> </manifest>
मिलती-जुलती जानकारी: नेटवर्क सुरक्षा कॉन्फ़िगरेशन
अपना ट्रस्ट मैनेजर बनाना
आपके टीएलएस चेकर को हर सर्टिफ़िकेट स्वीकार नहीं करना चाहिए. आपको ट्रस्ट मैनेजर सेट अप करने की ज़रूरत पड़ सकती है. साथ ही, टीएलएस से जुड़ी उन सभी चेतावनियों को मैनेज करना पड़ सकता है जो इस्तेमाल के इस उदाहरण में दी गई किसी एक शर्त के लागू होने पर मिलती हैं:
- आपने ऐसे वेब सर्वर से कम्यूनिकेट किया है जिसके सर्टिफ़िकेट पर, नए या कस्टम सीए ने हस्ताक्षर किया है.
- जिस डिवाइस का इस्तेमाल किया जा रहा है वह इस CA पर भरोसा नहीं करता.
- नेटवर्क सुरक्षा कॉन्फ़िगरेशन का इस्तेमाल नहीं किया जा सकता.
इन चरणों को पूरा करने के तरीके के बारे में ज़्यादा जानने के लिए, अज्ञात सर्टिफ़िकेट अथॉरिटी को मैनेज करने के बारे में चर्चा पढ़ें.
इसी विषय से जुड़ी जानकारी:
WebView ऑब्जेक्ट का इस्तेमाल ध्यान से करें
WebView
आपके ऐप्लिकेशन में मौजूद ऑब्जेक्ट, लोगों को ऐसी साइटों पर नेविगेट करने की अनुमति नहीं देनी चाहिए जिन पर आपका कंट्रोल नहीं है. जब भी संभव हो, अनुमति वाली सूची का इस्तेमाल करके, अपने ऐप्लिकेशन के WebView
ऑब्जेक्ट से लोड होने वाले कॉन्टेंट को सीमित करें.
इसके अलावा, JavaScript इंटरफ़ेस की सुविधा को कभी भी चालू न करें. ऐसा तब तक न करें, जब तक कि आपको अपने ऐप्लिकेशन के WebView
ऑब्जेक्ट के कॉन्टेंट पर पूरा भरोसा न हो और उस पर आपका पूरा कंट्रोल न हो.
एचटीएमएल मैसेज चैनल इस्तेमाल करना
अगर आपके ऐप्लिकेशन को Android 6.0 (एपीआई लेवल 23) और इसके बाद के वर्शन पर चलने वाले डिवाइसों पर JavaScript इंटरफ़ेस का इस्तेमाल करना है, तो वेबसाइट और अपने ऐप्लिकेशन के बीच कम्यूनिकेट करने के लिए, एचटीएमएल मैसेज चैनल का इस्तेमाल करें. इसके लिए, यहां दिए गए कोड स्निपेट का इस्तेमाल करें:
Kotlin
val myWebView: WebView = findViewById(R.id.webview) // channel[0] and channel[1] represent the two ports. // They are already entangled with each other and have been started. val channel: Array<out WebMessagePort> = myWebView.createWebMessageChannel() // Create handler for channel[0] to receive messages. channel[0].setWebMessageCallback(object : WebMessagePort.WebMessageCallback() { override fun onMessage(port: WebMessagePort, message: WebMessage) { Log.d(TAG, "On port $port, received this message: $message") } }) // Send a message from channel[1] to channel[0]. channel[1].postMessage(WebMessage("My secure message"))
Java
WebView myWebView = (WebView) findViewById(R.id.webview); // channel[0] and channel[1] represent the two ports. // They are already entangled with each other and have been started. WebMessagePort[] channel = myWebView.createWebMessageChannel(); // Create handler for channel[0] to receive messages. channel[0].setWebMessageCallback(new WebMessagePort.WebMessageCallback() { @Override public void onMessage(WebMessagePort port, WebMessage message) { Log.d(TAG, "On port " + port + ", received this message: " + message); } }); // Send a message from channel[1] to channel[0]. channel[1].postMessage(new WebMessage("My secure message"));
इसी विषय से जुड़ी जानकारी:
सही अनुमतियां देना
सिर्फ़ उतनी अनुमतियों का अनुरोध करें जितनी आपके ऐप्लिकेशन के ठीक से काम करने के लिए ज़रूरी हैं. जब आपके ऐप्लिकेशन को अनुमतियों की ज़रूरत न हो, तो उन्हें वापस ले लें.
अनुमतियों को बाद में देने के लिए इंटेंट का इस्तेमाल करना
जब भी हो सके, किसी ऐसी कार्रवाई को पूरा करने के लिए अपने ऐप्लिकेशन में अनुमति न जोड़ें जिसे किसी दूसरे ऐप्लिकेशन में पूरा किया जा सकता है. इसके बजाय, अनुरोध को किसी ऐसे ऐप्लिकेशन पर भेजने के लिए इंटेंट का इस्तेमाल करें जिसके पास पहले से ही ज़रूरी अनुमति है.
यहां दिए गए उदाहरण में बताया गया है कि READ_CONTACTS
और WRITE_CONTACTS
अनुमतियों का अनुरोध करने के बजाय, उपयोगकर्ताओं को सीधे तौर पर संपर्क ऐप्लिकेशन पर ले जाने के लिए इंटेंट का इस्तेमाल कैसे किया जाता है:
Kotlin
// Delegates the responsibility of creating the contact to a contacts app, // which has already been granted the appropriate WRITE_CONTACTS permission. Intent(Intent.ACTION_INSERT).apply { type = ContactsContract.Contacts.CONTENT_TYPE }.also { intent -> // Make sure that the user has a contacts app installed on their device. intent.resolveActivity(packageManager)?.run { startActivity(intent) } }
Java
// Delegates the responsibility of creating the contact to a contacts app, // which has already been granted the appropriate WRITE_CONTACTS permission. Intent insertContactIntent = new Intent(Intent.ACTION_INSERT); insertContactIntent.setType(ContactsContract.Contacts.CONTENT_TYPE); // Make sure that the user has a contacts app installed on their device. if (insertContactIntent.resolveActivity(getPackageManager()) != null) { startActivity(insertContactIntent); }
इसके अलावा, अगर आपके ऐप्लिकेशन को फ़ाइल-आधारित I/O (इनपुट/आउटपुट) करना है, जैसे कि स्टोरेज को ऐक्सेस करना या कोई फ़ाइल चुनना, तो उसे खास अनुमतियों की ज़रूरत नहीं होती. इसकी वजह यह है कि सिस्टम, आपके ऐप्लिकेशन की ओर से कार्रवाइयां पूरी कर सकता है. इससे भी बेहतर यह है कि जब कोई उपयोगकर्ता किसी यूआरआई पर कॉन्टेंट चुनता है, तो कॉल करने वाले ऐप्लिकेशन को चुने गए संसाधन की अनुमति मिल जाती है.
इसी विषय से जुड़ी जानकारी:
ऐप्लिकेशन के बीच सुरक्षित तरीके से डेटा शेयर करना
अपने ऐप्लिकेशन का कॉन्टेंट, अन्य ऐप्लिकेशन के साथ ज़्यादा सुरक्षित तरीके से शेयर करने के लिए, इन सबसे सही तरीकों को अपनाएं:
- ज़रूरत के मुताबिक, सिर्फ़ पढ़ने या सिर्फ़ लिखने की अनुमतियां लागू करें.
-
FLAG_GRANT_READ_URI_PERMISSION
औरFLAG_GRANT_WRITE_URI_PERMISSION
फ़्लैग का इस्तेमाल करके, क्लाइंट को डेटा का ऐक्सेस सिर्फ़ एक बार के लिए दें. - डेटा शेयर करते समय,
content://
यूआरआई का इस्तेमाल करें, न किfile://
यूआरआई का.FileProvider
आपके लिए यह काम करो.
यहां दिए गए कोड स्निपेट में बताया गया है कि किसी ऐप्लिकेशन की PDF फ़ाइल को अलग PDF व्यूअर ऐप्लिकेशन में दिखाने के लिए, यूआरआई की अनुमति देने वाले फ़्लैग और कॉन्टेंट प्रोवाइडर की अनुमतियों का इस्तेमाल कैसे किया जाता है:
Kotlin
// Create an Intent to launch a PDF viewer for a file owned by this app. Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("content://com.example/personal-info.pdf") // This flag gives the started app read access to the file. addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) }.also { intent -> // Make sure that the user has a PDF viewer app installed on their device. intent.resolveActivity(packageManager)?.run { startActivity(intent) } }
Java
// Create an Intent to launch a PDF viewer for a file owned by this app. Intent viewPdfIntent = new Intent(Intent.ACTION_VIEW); viewPdfIntent.setData(Uri.parse("content://com.example/personal-info.pdf")); // This flag gives the started app read access to the file. viewPdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // Make sure that the user has a PDF viewer app installed on their device. if (viewPdfIntent.resolveActivity(getPackageManager()) != null) { startActivity(viewPdfIntent); }
ध्यान दें: लिखने की अनुमति वाले ऐप्लिकेशन की होम डायरेक्ट्री से फ़ाइलें चलाने पर, W^X सिद्धांत का उल्लंघन होता है.
इस वजह से, Android 10 (एपीआई लेवल 29) और उसके बाद के वर्शन को टारगेट करने वाले ऐसे ऐप्लिकेशन जो भरोसेमंद नहीं हैं, वे ऐप्लिकेशन की होम डायरेक्ट्री में मौजूद फ़ाइलों पर exec()
को लागू नहीं कर सकते. वे सिर्फ़ ऐप्लिकेशन की APK फ़ाइल में एम्बेड किए गए बाइनरी कोड पर exec()
को लागू कर सकते हैं.
इसके अलावा, Android 10 और इसके बाद के वर्शन को टारगेट करने वाले ऐप्लिकेशन, मेमोरी में मौजूद उन फ़ाइलों के एक्ज़ीक्यूटेबल कोड में बदलाव नहीं कर सकते जिन्हें dlopen()
की मदद से खोला गया है. इसमें शेयर की गई ऐसी ऑब्जेक्ट (.so
) फ़ाइलें शामिल हैं जिनमें टेक्स्ट की जगह बदली गई है.
इसी विषय से जुड़ी जानकारी:
android:grantUriPermissions
डेटा को सुरक्षित तरीके से सेव करना
ऐसा हो सकता है कि आपके ऐप्लिकेशन को लोगों की संवेदनशील जानकारी को ऐक्सेस करने की ज़रूरत हो. हालांकि, लोग आपके ऐप्लिकेशन को अपना डेटा ऐक्सेस करने की अनुमति सिर्फ़ तब देते हैं, जब उन्हें भरोसा होता है कि आप उनके डेटा को सुरक्षित रखेंगे.
निजी डेटा को इंटरनल स्टोरेज में सेव करना
उपयोगकर्ता के सभी निजी डेटा को डिवाइस के इंटरनल स्टोरेज में सेव करें. यह स्टोरेज, हर ऐप्लिकेशन के लिए सैंडबॉक्स किया जाता है. आपके ऐप्लिकेशन को इन फ़ाइलों को देखने के लिए अनुमति का अनुरोध करने की ज़रूरत नहीं है. साथ ही, अन्य ऐप्लिकेशन इन फ़ाइलों को ऐक्सेस नहीं कर सकते. सुरक्षा को बेहतर बनाने के लिए, जब उपयोगकर्ता किसी ऐप्लिकेशन को अनइंस्टॉल करता है, तो डिवाइस उन सभी फ़ाइलों को मिटा देता है जिन्हें ऐप्लिकेशन ने इंटरनल स्टोरेज में सेव किया था.
यहां दिया गया कोड स्निपेट, इंटरनल स्टोरेज में डेटा लिखने का एक तरीका दिखाता है:
Kotlin
// Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. val FILE_NAME = "sensitive_info.txt" val fileContents = "This is some top-secret information!" File(filesDir, FILE_NAME).bufferedWriter().use { writer -> writer.write(fileContents) }
Java
// Creates a file with this name, or replaces an existing file // that has the same name. Note that the file name cannot contain // path separators. final String FILE_NAME = "sensitive_info.txt"; String fileContents = "This is some top-secret information!"; try (BufferedWriter writer = new BufferedWriter(new FileWriter(new File(getFilesDir(), FILE_NAME)))) { writer.write(fileContents); } catch (IOException e) { // Handle exception. }
नीचे दिया गया कोड स्निपेट, इंटरनल स्टोरेज से डेटा पढ़ने का तरीका दिखाता है:
Kotlin
val FILE_NAME = "sensitive_info.txt" val contents = File(filesDir, FILE_NAME).bufferedReader().useLines { lines -> lines.fold("") { working, line -> "$working\n$line" } }
Java
final String FILE_NAME = "sensitive_info.txt"; StringBuffer stringBuffer = new StringBuffer(); try (BufferedReader reader = new BufferedReader(new FileReader(new File(getFilesDir(), FILE_NAME)))) { String line = reader.readLine(); while (line != null) { stringBuffer.append(line).append('\n'); line = reader.readLine(); } } catch (IOException e) { // Handle exception. }
इसी विषय से जुड़ी जानकारी:
इस्तेमाल के उदाहरण के आधार पर, बाहरी स्टोरेज में डेटा सेव करना
बड़ी और संवेदनशील न होने वाली फ़ाइलों के लिए, बाहरी स्टोरेज का इस्तेमाल करें. ये फ़ाइलें सिर्फ़ आपके ऐप्लिकेशन के लिए होती हैं. साथ ही, ये वे फ़ाइलें होती हैं जिन्हें आपका ऐप्लिकेशन, अन्य ऐप्लिकेशन के साथ शेयर करता है. आपके ऐप्लिकेशन के लिए कौनसे एपीआई इस्तेमाल किए जाएंगे, यह इस बात पर निर्भर करता है कि आपका ऐप्लिकेशन, ऐप्लिकेशन से जुड़ी फ़ाइलों को ऐक्सेस करने के लिए डिज़ाइन किया गया है या शेयर की गई फ़ाइलों को ऐक्सेस करने के लिए.
अगर किसी फ़ाइल में निजी या संवेदनशील जानकारी शामिल नहीं है, लेकिन वह सिर्फ़ आपके ऐप्लिकेशन में उपयोगकर्ता के लिए काम की है, तो उसे बाहरी स्टोरेज में मौजूद, ऐप्लिकेशन के हिसाब से बनी डायरेक्ट्री में सेव करें.
अगर आपके ऐप्लिकेशन को ऐसी फ़ाइल को ऐक्सेस या सेव करना है जो अन्य ऐप्लिकेशन के लिए फ़ायदेमंद हो, तो इस्तेमाल के उदाहरण के आधार पर इनमें से किसी एक एपीआई का इस्तेमाल करें:
- मीडिया फ़ाइलें: ऐप्लिकेशन के बीच शेयर की गई इमेज, ऑडियो फ़ाइलें, और वीडियो को सेव करने और उन्हें ऐक्सेस करने के लिए, MediaStore API का इस्तेमाल करें.
- अन्य फ़ाइलें: शेयर की गई अन्य तरह की फ़ाइलों को सेव करने और उन्हें ऐक्सेस करने के लिए, स्टोरेज ऐक्सेस फ़्रेमवर्क का इस्तेमाल करें. इनमें डाउनलोड की गई फ़ाइलें भी शामिल हैं.
स्टोरेज वॉल्यूम की उपलब्धता देखना
अगर आपका ऐप्लिकेशन, हटाने लायक किसी बाहरी स्टोरेज डिवाइस के साथ इंटरैक्ट करता है, तो ध्यान रखें कि जब आपका ऐप्लिकेशन उस डिवाइस को ऐक्सेस करने की कोशिश कर रहा हो, तब उपयोगकर्ता उस स्टोरेज डिवाइस को हटा सकता है. यह पुष्टि करने के लिए कि स्टोरेज डिवाइस उपलब्ध है, लॉजिक शामिल करें.
डेटा की पुष्टि करना
अगर आपका ऐप्लिकेशन बाहरी स्टोरेज से डेटा का इस्तेमाल करता है, तो पक्का करें कि डेटा का कॉन्टेंट खराब न हुआ हो या उसमें बदलाव न किया गया हो. ऐसी फ़ाइलों को मैनेज करने के लिए लॉजिक शामिल करें जो अब स्टेबल फ़ॉर्मैट में नहीं हैं.
नीचे दिए गए कोड स्निपेट में, हैश वेरिफ़ायर का एक उदाहरण दिया गया है:
Kotlin
val hash = calculateHash(stream) // Store "expectedHash" in a secure location. if (hash == expectedHash) { // Work with the content. } // Calculating the hash code can take quite a bit of time, so it shouldn't // be done on the main thread. suspend fun calculateHash(stream: InputStream): String { return withContext(Dispatchers.IO) { val digest = MessageDigest.getInstance("SHA-512") val digestStream = DigestInputStream(stream, digest) while (digestStream.read() != -1) { // The DigestInputStream does the work; nothing for us to do. } digest.digest().joinToString(":") { "%02x".format(it) } } }
Java
Executor threadPoolExecutor = Executors.newFixedThreadPool(4); private interface HashCallback { void onHashCalculated(@Nullable String hash); } boolean hashRunning = calculateHash(inputStream, threadPoolExecutor, hash -> { if (Objects.equals(hash, expectedHash)) { // Work with the content. } }); if (!hashRunning) { // There was an error setting up the hash function. } private boolean calculateHash(@NonNull InputStream stream, @NonNull Executor executor, @NonNull HashCallback hashCallback) { final MessageDigest digest; try { digest = MessageDigest.getInstance("SHA-512"); } catch (NoSuchAlgorithmException nsa) { return false; } // Calculating the hash code can take quite a bit of time, so it shouldn't // be done on the main thread. executor.execute(() -> { String hash; try (DigestInputStream digestStream = new DigestInputStream(stream, digest)) { while (digestStream.read() != -1) { // The DigestInputStream does the work; nothing for us to do. } StringBuilder builder = new StringBuilder(); for (byte aByte : digest.digest()) { builder.append(String.format("%02x", aByte)).append(':'); } hash = builder.substring(0, builder.length() - 1); } catch (IOException e) { hash = null; } final String calculatedHash = hash; runOnUiThread(() -> hashCallback.onHashCalculated(calculatedHash)); }); return true; }
कैश फ़ाइलों में सिर्फ़ ऐसी जानकारी सेव करें जो संवेदनशील न हो
ऐप्लिकेशन के ऐसे डेटा को डिवाइस की कैश मेमोरी में सेव करें जिसे ऐक्सेस करने के लिए, संवेदनशील जानकारी की ज़रूरत नहीं होती. इससे, ऐप्लिकेशन के डेटा को तेज़ी से ऐक्सेस किया जा सकता है. अगर कैश मेमोरी का साइज़ 1 एमबी से ज़्यादा है, तो getExternalCacheDir()
का इस्तेमाल करें.
एक एमबी या इससे कम साइज़ वाली कैश मेमोरी के लिए, getCacheDir()
का इस्तेमाल करें.
दोनों तरीकों से आपको File
ऑब्जेक्ट मिलता है. इसमें आपके ऐप्लिकेशन का कैश मेमोरी में सेव किया गया डेटा होता है.
यहां दिए गए कोड स्निपेट में, उस फ़ाइल को कैश मेमोरी में सेव करने का तरीका बताया गया है जिसे आपके ऐप्लिकेशन ने हाल ही में डाउनलोड किया है:
Kotlin
val cacheFile = File(myDownloadedFileUri).let { fileToCache -> File(cacheDir.path, fileToCache.name) }
Java
File cacheDir = getCacheDir(); File fileToCache = new File(myDownloadedFileUri); String fileToCacheName = fileToCache.getName(); File cacheFile = new File(cacheDir.getPath(), fileToCacheName);
ध्यान दें: अगर आपने शेयर किए गए स्टोरेज में अपने ऐप्लिकेशन की कैश मेमोरी को रखने के लिए getExternalCacheDir()
का इस्तेमाल किया है, तो हो सकता है कि ऐप्लिकेशन के चालू होने के दौरान उपयोगकर्ता, इस स्टोरेज में मौजूद मीडिया को हटा दे. इसमें ऐसा लॉजिक शामिल करें जिससे उपयोगकर्ता के इस व्यवहार की वजह से, कैश मेमोरी में मौजूद डेटा न मिलने की समस्या को आसानी से ठीक किया जा सके.
चेतावनी: इन फ़ाइलों पर कोई सुरक्षा लागू नहीं की गई है.
इसलिए, Android 10 (एपीआई लेवल 29) या इससे पहले के वर्शन को टारगेट करने वाला कोई भी ऐप्लिकेशन, WRITE_EXTERNAL_STORAGE
अनुमति के साथ इस कैश मेमोरी के कॉन्टेंट को ऐक्सेस कर सकता है.
मिलती-जुलती जानकारी: डेटा और फ़ाइल स्टोरेज की खास जानकारी
निजी मोड में SharedPreferences का इस्तेमाल करना
अपने ऐप्लिकेशन के SharedPreferences
ऑब्जेक्ट बनाने या उन्हें ऐक्सेस करने के लिए, getSharedPreferences()
का इस्तेमाल करते समय MODE_PRIVATE
का इस्तेमाल करें. इस तरह, सिर्फ़ आपका ऐप्लिकेशन, शेयर की गई प्राथमिकताओं वाली फ़ाइल में मौजूद जानकारी को ऐक्सेस कर सकता है.
अगर आपको ऐप्लिकेशन के बीच डेटा शेयर करना है, तो SharedPreferences
ऑब्जेक्ट का इस्तेमाल न करें. इसके बजाय, ऐप्लिकेशन के बीच डेटा को सुरक्षित तरीके से शेयर करने के लिए, यह तरीका अपनाएं.
इसी विषय से जुड़ी जानकारी:
सेवाओं और डिपेंडेंसी को अप-टू-डेट रखना
ज़्यादातर ऐप्लिकेशन, खास टास्क पूरे करने के लिए बाहरी लाइब्रेरी और डिवाइस सिस्टम की जानकारी का इस्तेमाल करते हैं. अपने ऐप्लिकेशन की डिपेंडेंसी को अप-टू-डेट रखने से, इन कम्यूनिकेशन पॉइंट को ज़्यादा सुरक्षित बनाया जा सकता है.
Google Play services की सुरक्षा सेवा देने वाली कंपनी की जानकारी देखना
ध्यान दें: यह सेक्शन सिर्फ़ उन ऐप्लिकेशन पर लागू होता है जो Google Play services इंस्टॉल किए गए डिवाइसों को टारगेट करते हैं.
अगर आपका ऐप्लिकेशन Google Play services का इस्तेमाल करता है, तो पक्का करें कि यह उस डिवाइस पर अपडेट हो जिस पर आपका ऐप्लिकेशन इंस्टॉल है. जांच को एसिंक्रोनस तरीके से करें. ऐसा यूज़र इंटरफ़ेस (यूआई) थ्रेड से बाहर करें. अगर डिवाइस अपडेट नहीं है, तो अनुमति से जुड़ी गड़बड़ी ट्रिगर करें.
यह पता लगाने के लिए कि आपके ऐप्लिकेशन को इंस्टॉल करने वाले डिवाइस पर Google Play services का नया वर्शन है या नहीं, एसएसएल के गलत इस्तेमाल से बचाने के लिए, सुरक्षा सेवा देने वाली कंपनी को अपडेट करने के बारे में दी गई गाइड में बताया गया तरीका अपनाएं.
इसी विषय से जुड़ी जानकारी:
ऐप्लिकेशन की सभी डिपेंडेंसी अपडेट करें
ऐप्लिकेशन को डिप्लॉय करने से पहले, पक्का करें कि सभी लाइब्रेरी, एसडीके टूल, और अन्य डिपेंडेंसी अप-टू-डेट हों:
- पहले पक्ष की डिपेंडेंसी, जैसे कि Android SDK के लिए, Android Studio में मौजूद अपडेट करने वाले टूल का इस्तेमाल करें. जैसे, एसडीके मैनेजर.
- तीसरे पक्ष की डिपेंडेंसी के लिए, उन लाइब्रेरी की वेबसाइटें देखें जिनका इस्तेमाल आपका ऐप्लिकेशन करता है. साथ ही, उपलब्ध अपडेट और सुरक्षा पैच इंस्टॉल करें.
इसी विषय से जुड़ी जानकारी: बिल्ड डिपेंडेंसी जोड़ना
ज़्यादा जानकारी
अपने ऐप्लिकेशन को ज़्यादा सुरक्षित बनाने के तरीके के बारे में ज़्यादा जानने के लिए, यहां दिए गए रिसॉर्स देखें:
- ऐप्लिकेशन की मुख्य क्वालिटी सुरक्षा से जुड़ी चेकलिस्ट
- ऐप्लिकेशन की सुरक्षा को बेहतर बनाने वाला प्रोग्राम
- YouTube पर Android Developers चैनल
- Android Protected Confirmation: लेन-देन की सुरक्षा को बेहतर बनाना