بهترین راهکارهای امنیت اپلیکیشن اندروید

بهترین راهکارهای امنیت اپلیکیشن اندروید

امنیت اپلیکیشن اندروید

همیشه وقتی صحبت از برنامه نویسی و رد و بدل کردن داده بین برنامه های مختلف باشد، یکی از مهمترین مواردی که باید در نظر بگیریم تامین امنیت است. یعنی باید همه راه هایی که داده میتواند دزدیده شود یا از دست برود را مسدود کنیم. داده ها مهمترین دارایی های ما در دنیای دیجیتال هستند. پس وقتی که با این دارایی ها سر و کار داریم باید همه تلاش خودمان را بکنیم که اتفاق بدی برای آنها نیفتد. امروز میخواهیم در بلاگ برنامه چی، درباره بهترین راهکارهای تامین امنیت اپلیکیشن های اندروید صحبت کنیم.

امنیت یکی از بحث های بسیار مهم در اپلیکیشن های اندروید است که باعث افزایش اعتماد کاربران و همچنین حفاظت از اطلاعات و سلامت دستگاه های آن ها میشود. مواردی که در این صفحه بررسی میشوند شامل بهترین راهکار های تامین امنیت (Best Practices)، برقراری امنیت در ارتباط، معیار های ارتباط ایمن با سرور، دریافت مجوز های درست، ذخیره ایمن اطلاعات و به روز نگه داشتن کتابخانه های پروژه برای اپلیکیشن های اندرویدی هستند.


اجبار به برقراری امنیت در ارتباط

بهترین راهکارهای امنیت اپلیکیشن اندروید

یک اپلیکیشن میتواند با یک سرور اینترنتی یا با یک نرم افزار دیگر ارتباط داشته باشد. این راه های ارتباطی میتوانند محل آسیب های بسیار جدی باشند. وقتی که ما اطلاعات رد و بدل شده بین اپلیکیشن خودتان با دیگر اپلیکیشن ها، و یا بین اپلیکیشن خودتان و یک وبسایت را ایمن سازی میکنید، پایداری اپلیکیشن ما و ایمنی اطلاعاتی که ارسال و دریافت میکنید بسیار بیشتر میشود. اما چگونه باید این کار را انجام بدهیم؟


از Intent های صریح و Content Provider های export نشده استفاده کنیم

یکی از قدم ها در تامین امنیت اپلیکیشن، ایمن سازی استفاده از Intent ها و Content Provider های نرم افزار هاست. برای این کار میتوانیم قدم های زیر را انجام بدهیم.


یک انتخاب کننده اپلیکیشن نمایش بدهیم

در سناریوهایی که ممکن است کاربر برای انجام یک وظیفه به نرم افزار دیگری هدایت بشود، از Intent های ضمنی استفاده میکنیم. وقتی که یک Intent ضمنی توانایی باز کردن بیشتر از دو اپلیکیشن را روی دستگاه کاربر داشته باشد، باید حتما یک صفحه کوچک نشان بدهیم که کاربر بتواند اپلیکیشن های مناسب را از درون آن انتخاب کند. این استراتژی در تعامل با کاربر، به آنها اجازه میدهد که کارهای خود را با استفاده از اپلیکیشن هایی که به آنها اعتماد دارند انجام بدهند و داده ها را با مسئولیت خودشان کنترل کنند. مثال زیر را مشاهده کنیم.

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

از Permission های Signature-Based استفاده کنیم

وقتی بین دو اپلیکیشن که خودمان مالک آنها هستیم یا آنها را کنترل میکنیم اطلاعات خاصی را به اشتراک میگذاریم، بهتر است از Permission های Signature-Based استفاده کنیم. این مدل از Permission ها نیاز به تایید کاربر ندارد و به جای آن بررسی میکنند که اپلیکیشن هایی که به داده ها دسترسی دارند، یک کلید امضای یکسان داشته باشند. به همین دلیل، این Permission ها جریان کاری و تجربه کاربری بسیار ایمن تری را ارائه میدهند. مثال زیر را مشاهده کنیم:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp">
    <permission android:name="my_custom_permission_name"
                android:protectionLevel="signature" />

اجازه دسترسی به Content Provider های اپلیکیشن خودتان را ندهید

به غیر از مواردی که خودمان قصد داشته باشیم داده هایی را برای یک اپلیکیشن دیگر که مال خودمان نیست بفرستیم، باید همیشه بصورت صریح اجازه دسترسی دیگر برنامه ها به Content Provider های اپلیکیشن خودمان را مسدود کنیم. این مورد مخصوصا اگر اپلیکیشن ما قرار باشد روی دستگاه هایی با اندروید 4.1.1 (API 16) و پایینتر اجرا بشود، بسیار اهمیت پیدا میکند. به این دلیل که مقدار ویژگی android:exported برای تگ <provider> در این ورژن ها، بصورت پیشفرض برابر با 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>

قبل از نشان دادن اطلاعات حساس، همیشه مدارک کافی را درخواست کنیم

همیشه باید برای نشان دادن اطلاعات حساس به کاربر، از اینکه کاربر واقعا مالک دستگاه است مطمئن شویم. پس همیشه باید قبل از نمایش این مدل داده ها، مدرکی را برای تایید هویت از کاربر دریافت کنیم. وقتی که میخواهیم مدارک لازم را برای نشان دادن اطلاعات حساس یا محتوای پریمیوم از کاربر دریافت کنیم، میتوانیم با درخواست پین/پسورد/الگو یا استفاده از سنسور های بیومتریک مانند حسگر اثر انگشت، این موارد را از کاربر بگیریم.


معیار های امنیت شبکه را پیاده سازی کنیم

ارتباط با سرور یکی از مواردی است که میتواند امنیت اپلیکیشن ما را به خطر بیاندازد. بخش های زیر به صورت کامل توضیح میدهند که چگونه میتوانیم امنیت ارتباط با شبکه را برای اپلیکیشن های خودمان تقویت کنیم.


از ترافیک SSL استفاده کنیم

اگر از وب سرور هایی استفاده کنیم که دارای یک گواهینامه معتبر SSL باشند، به راحتی میتوانیم درخواست HTTPS برای سرور ارسال کنیم. به مثال زیر توجه کنیم:

val url = URL("https://www.google.com")
val urlConnection = url.openConnection() as HttpsURLConnection
urlConnection.connect()
urlConnection.inputStream.use {
    ...
}

یک کانفیگ امنیت شبکه به اپلیکیشن اضافه کنیم

اگر سرور های اپلیکیشن ما از یک CA جدید و یا کاستوم استفاده میکنند، میتوانیم تنظیمات امنیتی شبکه را برای سرور های خودمان، درون یک فایل Configuration اضافه بریزیم و در پروژه قرار بدهیم. با استفاده از قدم های زیر میتوانیم بدون درگیر شدن با کدنویسی، یک فایل Configuration برای شبکه اپلیکیشن بسازیم و به آن اضافه کنیم:

برای اضافه کردن یک فایل کانفیگ شبکه به پروژه خودمان، مرحله های زیر را انجام میدهیم:

1- داخل Manifest پروژه، فایل کانفیگ را تعریف میکنیم.

<manifest ... >
    <application
        android:networkSecurityConfig="@xml/network_security_config"
        ... >
        <!-- Place child elements of <application> element here. -->
    </application>
</manifest>

2- یک فایل XML را به آدرس زیر اضافه میکنیم:

res/xml/network_security_config.xml

با غیر فعال کردن clear-text باید برای اپلیکیشن تعریف کنیم که همه ترافیک اپلیکیشن روی دامنه های خاص، باید فقط از طریق HTTPS ارسال و دریافت شود.

<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>

Trust Manager مخصوص خودتان را بسازید

بررسی کننده SSL ما، نباید هر گواهینامه ای را قبول کند. ممکن است که نیاز داشته باشیم یک Trust Manager بسازیم و همه خطاها و اخطارهایی که توسط SSL ایجاد میشوند را در آن مدیریت کنیم. این اخطار ها ممکن است در یکی از شرایط زیر به وجود بیایند:

  • ما در حال ارتباط با یک وب سرور باشیم که گواهینامه اش توسط یک CA جدید یا کاستوم امضا (Sign) شده است.
  • CA مورد نظر توسط دستگاه ما مورد اعتماد شناخته نمیشود.
  • نمیتوانیم از یک Configuration امنیتی برای شبکه استفاده کنیم.

در استفاده از WebView با احتیاط عمل کنید

هروقت امکان داشت، فقط محتوایی که در لیست مجاز ما هستند را درون آبجکت های WebView نمایش بدهیم. به زبان ساده تر، آبجکت WebView نباید به کاربر اجازه بدهد به سایت هایی وارد شوند که در حوزه کنترل ما نیستند. علاوه بر اینها، ما هیچوقت نباید JavaScript Interface Support را فعال کنیم. مگر اینکه کاملا به آبجکت های WebView موجود در اپلیکیشن خودمان اعتماد داشته باشیم.


از کانال های پیام رسانی HTML استفاده کنید

اگر اپلیکیشن ما باید حتما از JavaScript Interface Support استفاده کند، روی دستگاه هایی که اندروید 6.0 (API 23) به بالا را اجرا میکنند، میتوانیم به جای ارتباط بین اپلیکیشن و سایت از کانال های پیام رسانی HTML استفاده کنیم. به عنوان نمونه از تکه کد زیر را مشاهده کنید:

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"))

از Permission های درست استفاده کنید

permission های امنیت اپلیکیشن اندروید

یکی از موارد مهم در امنیت اپلیکیشن ها، مجوز هایی است که از کاربر دریافت میکنیم. به هرکدام از این مجوز ها یک Permission گفته میشود که انواع مختلفی از آنها در سیستم عامل اندروید وجود دارند. همیشه یادتان باشد اپلیکیشن ما باید کمترین Permission هایی که برای کار کردن نیاز دارد را از کاربر درخواست کند. وقتی هم که نیاز اپلیکیشن به آنها برطرف شد، باید Permission ها را آزاد کنیم. از راهکار های زیر برای بهینه سازی هرچه بیشتر مجوز ها در اپلیکیشن های خود استفاده کنید.


از Intent ها برای به تعویق انداختن Permission ها استفاده کنید

اگر امکان داشت وظیفه ای را با استفاده از یک اپلیکیشن دیگر انجام بدهیم، نباید برای همان وظیفه یک Permission به اپلیکیشن خودمان اضافه کنیم. به جای این کار، توسط Intent ها کاری بکنید تا از اپلیکیشن دیگری استفاده شود که قبلا آن Permission مورد نیاز را داشته باشد (یعنی تا حد امکان وظیفه ها رو برون سپاری کنیم که بقیه اپ ها برامون انجام بدن).

مثال زیر نشان میدهد که چگونه به جای درخواست کردن Permission های READ_CONTACTS و WRITE_CONTACTS به راحتی میتوانیم کاربر را به اپلیکیشن Contacts هدایت کنیم که از قبل این مجوز ها را دارد.

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

علاوه بر این، گر اپلیکیشن ما نیاز داشت کارهایی را با جریان I/O (ورودی و خروجی) فایل انجام بدهد، مانند دسترسی به حافظه ذخیره سازی و انتخاب یک فایل خاص، نیاز به Permission خاصی نداریم. زیرا سیستم عامل اندروید میتواند این کار را از طرف اپلیکیشن ما انجام بدهد. به عبارت دیگر، بعد از اینکه کاربر یک منبع خاص را درخواست میکند، اپلیکیشن مورد نظر مجوز لازم برای منبع خواسته شده را از طرف سیستم دریافت میکند.


داده ها را بصورت ایمن بین اپلیکیشن ها ارسال کنید

از موارد مهم در امنیت اپلیکیشن، ارسال داده ها برای دیگران و بین ماژول های داخلی نرم افزار میباشد. برای اینکه بتوانیم داده های خودمان را به صورت ایمن بین اپلیکیشن های مختلف به اشتراک بگذاریم، نیاز داریم که قدم های زیر را دنبال کنید:

  • حتما باید از Permission های read-only و write-only با توجه به نیاز استفاده کنید.
  • با استفاده از پرچم های زیر، فقط امکان یکبار دسترسی Client به داده ها را بدهید:
    FLAG_GRANT_READ_URI_PERMISSION و FLAG_GRANT_WRITE_URI_PERMISSION
  • وقتی که داده ها را به اشتراک میگذارید، به جای آدرس “file://” از “content://” استفاده کنید. البته آبجکت FileProvider بصورت اتوماتیک این کار را برای شما انجام میدهد.

تکه کد زیر نشان میدهد که چگونه از پرچم های URI Permission یا Content Provider Permission ها برای نمایش PDF یک اپلیکیشن در یک اپلیکیشن نمایش دهنده PDF استفاده کنیم.

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

نکته: اپلیکیشن های غیرقابل اعتماد (Untrusted) بعد از اندروید ورژن 10 (API 29) نمیتوانند متد exec() را روی فایل هایی که در مسیر اصلی اپلیکیشن قراردارند اجرا کنند. این اپلیکیشن ها باید فقط کدهای باینری که درون فایل APK وجود دارد را اجرا کنند. علاوه بر این، اپلیکشن هایی که روی اندروید ورژن 10 و بالاتر اجرا میشوند، نمیتوانند فایل های کد که با استفاده از dlopen() باز شده اند را تغییر بدهند یا اصلاح کنند. این مورد شامل همه فایل های آبجکت (.so) که با متن جایگزین شده اند نیز میشود.


داده ها را به صورت ایمن ذخیره کنید

ذخیره داده ها امنیت اپلیکیشن اندروید

هرچند در بعضی موارد ممکن است اپلیکیشن ما نیاز به دسترسی به اطلاعات حساس کاربر را داشته باشد، اما کاربر فقط زمانی به ما این اجازه را میدهد که مطمئن باشد اطلاعاتش بصورت ایمن ذخیره و نگهداری میشوند. پس امنیت اپلیکیشن تاثیر بسیار زیادی روی اعتماد سازی و جذب کاربران بیشتر دارد. اما چگونه میتوانیم این اطمینان را به کاربر بدهیم؟


داده های خصوصی را درون حافظه داخلی ذخیره کنید

باید همه داده های خصوصی کاربر را روی حافظه داخلی، که برای هر اپلیکیشن بصورت مجزا در نظر گرفته میشود، ذخیره کنیم. اپلیکیشن ما برای مشاهده این فایل ها نیاز به دریافت مجوز (Permission) از کاربر ندارد. همچنین بقیه اپلیکیشن ها اجازه دسترسی به این فایل ها را نخواهند داشت. به عنوان یکی دیگر از معیار های امنیت اپلیکیشن، وقتی که کاربر نرم افزار ما را حذف میکند، سیستم همه این فایل ها را به صورت اتوماتیک از روی حافظه پاک خواهد کرد.

اگر داده هایی که ذخیره میکنیم بسیار حساس یا خصوصی هستند، میتوانیم به جای آبجکت های File، با آبجکت های EncryptedFile که در کتابخانه های امنیتی وجود دارند کار کنیم.

کدهای زیر یکی از راه های نوشتن اطلاعات روی حافظه داخلی اپلیکیشن را نشان میدهند:

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val mainKey = MasterKey.Builder(applicationContext)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()

// Create a file with this name, or replace an entire existing file
// that has the same name. Note that you cannot append to an existing file,
// and the file name cannot contain path separators.
val fileToWrite = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    applicationContext,
    File(DIRECTORY, fileToWrite),
    mainKey,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val fileContent = "MY SUPER-SECRET INFORMATION"
        .toByteArray(StandardCharsets.UTF_8)
encryptedFile.openFileOutput().apply {
    write(fileContent)
    flush()
    close()
}

کدهای زیر عملیات برعکس کدهای بالا را نشان میدهند. یعنی خواندن اطلاعات از حافظه:

// Although you can define your own key generation parameter specification, it's
// recommended that you use the value specified here.
val mainKey = MasterKey.Builder(applicationContext)
        .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
        .build()
val fileToRead = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(
    applicationContext,
    File(DIRECTORY, fileToRead),
    mainKey,
    EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build()

val inputStream = encryptedFile.openFileInput()
val byteArrayOutputStream = ByteArrayOutputStream()
var nextByte: Int = inputStream.read()
while (nextByte != -1) {
    byteArrayOutputStream.write(nextByte)
    nextByte = inputStream.read()
}

val plaintext: ByteArray = byteArrayOutputStream.toByteArray()

بر اساس کاربرد اپلیکیشن، داده ها را روی حافظه خارجی ذخیره کنید

میتوانیم برای ذخیره کردن فایل های حجیم، غیر حساس و همچنین فایل هایی که قصد داریم آنها را با دیگر اپلیکیشن ها به اشتراک بگذاریم، از حافظه خارجی دستگاه استفاده کنیم. انتخاب کردن API هایی که استفاده میکنیم به این موضوع بستگی دارند که اپلیکیشن ما برای چه کاری طراحی شده است. دسترسی به فایل های مخصوص اپلیکیشن، یا فایل های Share شده اپلیکیشن؟ در هر صورت باید عمل های زیر را انجام بدهیم.


در درسترس بودن سطح حافظه را چک کنید

اگر اپلیکیشن ما با یک حافظه خارجی قابل جدا شدن (Removable) تعامل میکند، باید این نکته را در نظر داشته باشیم که کاربر میتواند در هنگام کار کردن اپلیکیشن، این حافظه را از دستگاه جدا کند. پس باید در کدهای اپ، روند بررسی وجود و قابل دسترس بودن حافظه را همیشه بررسی کنیم.


به فایل های مخصوص اپلیکیشن دسترسی پیدا کنید

اگر یک فایل شامل اطلاعات خصوصی و حساس نباشد، ولی برای کاربر، فقط در اپلیکیشن ما ارزشمند باشد میتوانیم آن را در دایرکتوری مخصوص فایل های اپلیکیشن، در حافظه خارجی ذخیره کنیم.


به فایل های Share شده دسترسی داشته باشید

اگر اپلیکیشن ما نیاز به دسترسی یا ذخیره سازی فایلی دارد که برای دیگر اپلیکیشن ها ارزشمند است، بر اساس نیاز از یکی از API های زیر استفاده میکنیم:

  • فایل های Media: برای ذخیره سازی و دسترسی به فایل های تصویر، صدا و ویدئو که بین اپلیکیشن های دیگر به اشتراک گذاشته شده اند، میتوانیم از Media Store API استفاده کنیم.
  • فایل های دیگر: برای ذخیره سازی و دسترسی به انواع دیگر فایل های به اشتراک گذاشته شده، مانند فایل های دانلودی، میتوانیم از Storage Access Framework استفاده کنیم.

اعتبار داده ها را چک کنید

اگر اپلیکیشن ما از داده های روی حافظه خارجی استفاده میکند، باید مطمئن شویم که محتویات این فایل ها خراب شده یا دستکاری شده نباشند. یعنی اپلیکیشن ما باید دارای منطق های مورد نیاز برای مدیریت فایل هایی که دیگر پایداری لازم را ندارند نیز باشد. مثالی از اعتبار سنجی Hash را میتوانید در کدهای زیر ببینید:

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

فقط فایل های غیر حساس را در کش ذخیره کنید

ما میتوانیم برای دسترسی سریعتر به داده های غیر حساس، آنها را در حافظه کش دستگاه ذخیره کنیم. برای کش هایی که بیشتر از 1 مگابایت حجم دارند، میتوانیم از متد getExternalCacheDir(); یا از متد getCacheDir(); استفاده کنیم. هر کدام از این متد ها یک آبجکت از کلاس File را برمیگردانند که شامل فایل های کش شده دستگاه هستند.

تکه کد زیر نشان میدهد که چگونه میتوانیم فایلی که تازه دانلود شده را در کش ذخیره کنیم:

val cacheFile = File(myDownloadedFileUri).let { fileToCache ->
    File(cacheDir.path, fileToCache.name)
}

نکته: اگر از متد getExternalCacheDir(); استفاده کنیم تا کش اپلیکیشن را درون حافظه اشتراکی قرار بدهیم، کاربر ممکن است حافظه را وقتی اپلیکیشن در حال کار کردن باشد، از دستگاه جدا کند. پس ما باید منطقی را در اپ پیاده کنیم که اگر فایل های کش در اثر رفتار نادرست کاربر از بین رفتند، بتواند این وضعیت را مدیریت کند.

هشدار: دقت داشته باشید این فایل ها هیج امنیتی ندارند. بنابراین هر اپلیکیشنی که برای اندروید 10 به پایین نوشته شده باشد، دارای مجوز WRITE_EXTERNAL_STORAGE است که میتواند به محتویات کش دسترسی داشته باشد.


از SharedPreferences در حالت خصوصی استفاده کنید

وقتی که برای دسترسی به آبجکت SharedPreferences اپلیکیشن خودمان، از متد getSharedPreferences() استفاده میکنیم، حتما باید MODE_PRIVATE را هم به آن اضافه کنیم. با این کار، فقط اپلیکیشن خودمان میتواند به فایل های موجود در آن دسترسی داشته باشد.

اگر بخواهیم داده ها را بین اپلیکیشن های دیگر به اشتراک بگذاریم، نباید از آبجکت SharedPreference() استفاده کنیم. به جای آن باید از دستورالعمل های به اشتراک گذاری داده ها بصورت ایمن بین اپلیکیشن ها استفاده کنیم.


سرویس ها و Dependency ها را به روز نگه دارید

به روز رسانی امنیت اپلیکیشن اندروید

بیشتر اپلیکیشن ها برای انجام وظیفه های مختلف، از کتابخانه های خارجی و اطلاعات سیستم دستگاه استفاده میکنند. با به روز نگه داشتن Dependency های اپلیکیشن خودمان میتوانیم امنیت اپلیکیشن را تا حدود زیادی بهبود بدهیم.


سرویس های گوگل پلی را بررسی کنید

نکته: این بخش فقط مربوط به دستگاه هایی است که سرویس های Google Play Services روی آنها نصب شده باشد.

اگر اپلیکیشن ما از Google Play Services استفاده میکند، همیشه باید مطمئن شویم این سرویس ها روی دستگاهی که اپلیکیشن ما روی آن اجرا میشود، آپدیت شده باشند. روند بررسی این موضوع باید روی یک Thread جدید انجام بشود و روی Thread اصلی (UI Thread) نباشد. اگر دستگاه مورد نظر آپدیت نشده باشد، اپلیکیشن ما باید یک خطای اهراز هویت به کاربر نشان بدهد.


همه Dependency ها را به روز رسانی کنید

همیشه قبل از اجرای پیاده سازی اپلیکیشن باید مطمئن شویم همه کتابخانه ها، SDK ها و بقیه Dependency ها همه به روز رسانی شده اند. میتوانید مراحل زیر را انجام بدهیم:

  • برای Dependency های داخلی اندروید مانند Android SDK، از ابزار های موجود در اندروید استودیو، مانند SDK Manager استفاده کنید.
  • برای Dependency های خارجی، وبسایت کتابخانه هایی که در اپلیکیشن استفاده کرده اید را بررسی کنید. سپس همه آپدیت های ارائه شده برای آنها را در پروژه خودتان اعمال کنید.

منابع بیشتر برای مطالعه

مطالعه بیشتر امنیت اپلیکیشن اندروید

میتوانید از لینک های زیر برای مطالعه بیشتر درباره امنیت اپلیکیشن استفاده کنید:

درباره نویسنده

دیدگاه‌ خود را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

اسکرول به بالا