שיפור האבטחה של האפליקציה

כשמשפרים את האבטחה של האפליקציה, עוזרים לשמור על אמון המשתמשים ועל תקינות המכשיר.

בדף הזה מוצגות כמה שיטות מומלצות שיש להן השפעה חיובית משמעותית על האבטחה של האפליקציה.

אכיפת תקשורת מאובטחת

כששומרים על אבטחת הנתונים שמתחלפים בין האפליקציה שלכם לאפליקציות אחרות, או בין האפליקציה שלכם לאתר, משפרים את היציבות של האפליקציה ומגינים על הנתונים שאתם שולחים ומקבלים.

הגנה על התקשורת בין אפליקציות

כדי לתקשר בין אפליקציות בצורה בטוחה יותר, כדאי להשתמש בכוונות משתמעות עם בורר אפליקציות, בהרשאות שמבוססות על חתימות ובספקי תוכן שלא מיוצאים.

הצגת בורר אפליקציות

אם כוונה משתמעת יכולה להפעיל לפחות שתי אפליקציות אפשריות במכשיר של המשתמש, צריך להציג בבירור בורר אפליקציות. אסטרטגיית האינטראקציה הזו מאפשרת למשתמשים להעביר מידע רגיש לאפליקציה שהם סומכים עליה.

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 (API ברמה 16) ואילך, כי הערך שמוגדר כברירת מחדל למאפיין android:exported של האלמנט <provider> הוא true בגרסאות האלה של Android.

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

בקשה לפרטי כניסה לפני הצגת מידע רגיש

כשאתם מבקשים ממשתמשים להזין פרטי כניסה כדי שיוכלו לגשת למידע אישי רגיש או לתוכן פרימיום באפליקציה, בקשו מהם להזין קוד אימות, סיסמה או קו ביטול נעילה, או פרטי כניסה ביומטריים כמו זיהוי פנים או זיהוי טביעת אצבע.

למידע נוסף על שליחת בקשה לפרטי כניסה ביומטריים, ראו המדריך בנושא אימות ביומטרי.

החלת אמצעי אבטחה ברשת

בקטעים הבאים מוסבר איך לשפר את אבטחת הרשת של האפליקציה.

שימוש בתעבורת TLS

אם האפליקציה שלכם מתקשרת עם שרת אינטרנט שיש לו אישור שהונפק על ידי רשות אישורים (CA) מהימנה וידועה, צריך להשתמש בבקשת HTTPS כמו זו:

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();

הוספת הגדרה של אבטחת רשת

אם האפליקציה שלכם משתמשת ברשויות אישורים חדשות או בהתאמה אישית, תוכלו להצהיר על הגדרות האבטחה של הרשת בקובץ תצורה. התהליך הזה מאפשר ליצור את ההגדרה בלי לשנות את קוד האפליקציה.

כדי להוסיף לאפליקציה קובץ תצורה של אבטחת רשת:

  1. מגדירים את ההגדרה במניפסט של האפליקציה:
  2. <manifest ... >
        <application
            android:networkSecurityConfig="@xml/network_security_config"
            ... >
            <!-- Place child elements of <application> element here. -->
        </application>
    </manifest>
    
  3. מוסיפים קובץ משאב XML שנמצא ב-res/xml/network_security_config.xml.

    כדי לציין שכל התנועה לדומיינים מסוימים חייבת להשתמש ב-HTTPS, משביתים את הטקסט ללא הצפנה:

    <network-security-config>
        <domain-config cleartextTrafficPermitted="false">
            <domain includeSubdomains="true">secure.example.com</domain>
            ...
        </domain-config>
    </network-security-config>
    

    במהלך תהליך הפיתוח, אפשר להשתמש ברכיב <debug-overrides> כדי לאפשר באופן מפורש אישורים שהותקנו על ידי משתמשים. האלמנט הזה מבטל את האפשרויות של האפליקציה שחשובות לאבטחה במהלך ניפוי הבאגים והבדיקה, בלי להשפיע על הגדרת הגרסה שפורסמה. קטע הקוד הבא מראה איך מגדירים את האלמנט הזה בקובץ ה-XML של הגדרות האבטחה ברשת של האפליקציה:

    <network-security-config>
        <debug-overrides>
            <trust-anchors>
                <certificates src="user" />
            </trust-anchors>
        </debug-overrides>
    </network-security-config>
    

מידע קשור: הגדרת אבטחת הרשת

יצירת מנהל אמון משלכם

בודק ה-TLS לא אמור לקבל כל אישור. יכול להיות שתצטרכו להגדיר מנהל אמון ולטפל בכל האזהרות של TLS שמופיעות אם אחד מהמצבים הבאים רלוונטי לתרחיש לדוגמה שלכם:

  • אתם מתקשרים עם שרת אינטרנט שיש לו אישור שנחתם על ידי רשות אישורים חדשה או מותאמת אישית.
  • המכשיר שבו אתם משתמשים לא סומך על רשות האישורים הזו.
  • אי אפשר להשתמש בתצורה של אבטחת הרשת.

למידע נוסף על ביצוע השלבים האלה, אפשר לעיין בקטע בנושא טיפול ברשות אישורים לא מוכרת.

מידע קשור:

שימוש זהיר באובייקטים של WebView

אובייקטים מסוג WebView באפליקציה לא אמורים לאפשר למשתמשים לנווט לאתרים שאינם בשליטתכם. כשהדבר אפשרי, כדאי להשתמש ברשימת ההיתרים כדי להגביל את התוכן שנטען על ידי אובייקטים מסוג WebView באפליקציה.

בנוסף, לעולם אל תפעילו תמיכה בממשק JavaScript, אלא אם אתם שולטים לחלוטין בתוכן באובייקטים WebView של האפליקציה ואתם סומכים עליו.

שימוש בערוצים להעברת הודעות ב-HTML

אם האפליקציה שלכם חייבת להשתמש בתמיכה בממשק JavaScript במכשירים עם Android 6.0 (רמת API 23) ואילך, צריך להשתמש בערוצי הודעות HTML במקום בתקשורת בין אתר לאפליקציה, כפי שמתואר בקטע הקוד הבא:

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

מידע קשור:

מתן ההרשאות המתאימות

בקשו רק את מספר ההרשאות המינימלי שנחוץ לאפליקציה כדי לפעול כראוי. כשאפשר, כדאי לבטל את ההרשאות כשלא צריך אותן יותר.

שימוש בכוונות כדי לדחות הרשאות

כשהדבר אפשרי, אל תוסיפו לאפליקציה הרשאה לביצוע פעולה שאפשר לבצע באפליקציה אחרת. במקום זאת, השתמשו בכוונה (intent) כדי להעביר את הבקשה לאפליקציה אחרת שכבר יש לה את ההרשאה הנדרשת.

בדוגמה הבאה מוסבר איך להשתמש בכוונה (intent) כדי להפנות משתמשים לאפליקציית אנשי קשר במקום לבקש את ההרשאות 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);
}

בנוסף, אם האפליקציה צריכה לבצע פעולות קלט/פלט שמבוססות על קבצים – כמו גישה לאחסון או בחירה בקובץ – היא לא צריכה הרשאות מיוחדות כי המערכת יכולה להשלים את הפעולות בשם האפליקציה. יתרה מכך, אחרי שמשתמש בוחר תוכן בכתובת URI מסוימת, לאפליקציה המפעילה ניתנת הרשאה למשאב שנבחר.

מידע קשור:

שיתוף נתונים בצורה מאובטחת בין אפליקציות

כדי לשתף את התוכן של האפליקציה עם אפליקציות אחרות בצורה מאובטחת יותר, מומלץ לפעול לפי השיטות המומלצות הבאות:

  • לאכוף הרשאות קריאה בלבד או הרשאות כתיבה בלבד לפי הצורך.
  • הענקת גישה חד-פעמית לנתונים ללקוחות באמצעות הדגלים FLAG_GRANT_READ_URI_PERMISSION ו-FLAG_GRANT_WRITE_URI_PERMISSION.
  • כשמשתפים נתונים, צריך להשתמש במזהי URI מסוג content:// ולא במזהי URI מסוג file://. מכונות של FileProvider עושות זאת בשבילכם.

קטע הקוד הבא מראה איך משתמשים בדגלים להענקת הרשאות URI ובהרשאות של ספקי תוכן כדי להציג קובץ 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 ואילך (רמת API 29 ואילך) לא יכולות להפעיל את exec() בקובצי ספריית הבית של האפליקציה, אלא רק את הקוד הבינארי שמוטמע בקובץ ה-APK של האפליקציה. בנוסף, אפליקציות שמטרגטות את 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.
}

מידע קשור:

אחסון נתונים באחסון חיצוני על סמך תרחיש לדוגמה

כדאי להשתמש באחסון חיצוני לקבצים גדולים ולא רגישים שספציפיים לאפליקציה, וגם לקבצים שהאפליקציה משתפת עם אפליקציות אחרות. ממשקי ה-API הספציפיים שבהם אתם משתמשים תלויים בכך שהאפליקציה שלכם מיועדת לגשת לקבצים ספציפיים לאפליקציה או לגשת לקבצים משותפים.

אם קובץ לא מכיל מידע אישי או רגיש אבל מספק ערך למשתמש רק באפליקציה, כדאי לאחסן את הקובץ בספרייה ספציפית לאפליקציה באחסון חיצוני.

אם האפליקציה שלכם צריכה לגשת לקובץ או לאחסן אותו כדי לספק ערך לאפליקציות אחרות, תוכלו להשתמש באחד מממשקי ה-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;
}

שמירת נתונים לא רגישים בלבד בקובצי מטמון

כדי לספק גישה מהירה יותר לנתוני אפליקציות שאינם רגישים, כדאי לשמור אותם במטמון של המכשיר. למטמון גדול מ-1MB, משתמשים ב-getExternalCacheDir(). למטמון בנפח 1MB ומטה, משתמשים ב-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 (רמת API 29) או לגרסאות ישנות יותר, ויש לה את ההרשאה WRITE_EXTERNAL_STORAGE, יכולה לגשת לתוכן של המטמון הזה.

מידע קשור: סקירה כללית על אחסון נתונים וקבצים

שימוש ב-SharedPreferences במצב פרטי

כשמשתמשים ב-getSharedPreferences() כדי ליצור או לגשת לאובייקטים מסוג SharedPreferences של האפליקציה, צריך להשתמש ב-MODE_PRIVATE. כך רק לאפליקציה שלכם תהיה גישה למידע בקובץ ההעדפות המשותף.

אם רוצים לשתף נתונים בין אפליקציות, לא משתמשים באובייקטים מסוג SharedPreferences. במקום זאת, יש לפעול לפי השלבים לשיתוף נתונים באופן מאובטח בין אפליקציות.

ספריית האבטחה מספקת גם את הכיתה EncryptedSharedPreferences, שמקיפה את הכיתה SharedPreferences ומצפינה מפתחות וערכים באופן אוטומטי.

מידע קשור:

עדכון השירותים ויחסי התלות

רוב האפליקציות משתמשות בספריות חיצוניות ובמידע על מערכת המכשיר כדי לבצע משימות ייעודיות. אם תעדכנו את יחסי התלות של האפליקציה, נקודות התקשורת האלה יהיו מאובטחות יותר.

בדיקת ספק האבטחה של Google Play Services

הערה: הקטע הזה רלוונטי רק לאפליקציות שמטרגטות מכשירים שבהם מותקנת Google Play Services.

אם האפליקציה שלכם משתמשת ב-Google Play Services, חשוב לוודא שהיא מעודכנת במכשיר שבו היא מותקנת. לבצע את הבדיקה באופן אסינכרוני, מחוץ לשרשור של ממשק המשתמש. אם המכשיר לא מעודכן, תופעל שגיאת הרשאה.

כדי לבדוק אם Google Play Services עדכני במכשיר שבו מותקנת האפליקציה, פועלים לפי השלבים במדריך בנושא עדכון ספק האבטחה כדי להגן מפני ניצול לרעה של SSL.

מידע קשור:

עדכון כל יחסי התלות של האפליקציה

לפני פריסת האפליקציה, חשוב לוודא שכל הספריות, ערכות ה-SDK ויחסי התלות האחרים מעודכנים:

  • עבור יחסי תלות מאינטראקציה ישירה, כמו Android SDK, משתמשים בכלי העדכון שנמצאים ב-Android Studio, כמו SDK Manager.
  • לגבי יחסי תלות של צד שלישי, כדאי לבדוק את האתרים של הספריות שבהן האפליקציה משתמשת ולהתקין את כל העדכונים ותיקוני האבטחה הזמינים.

מידע קשור: הוספת יחסי תלות ל-build

מידע נוסף

למידע נוסף על שיפור האבטחה באפליקציה, תוכלו לעיין במקורות המידע הבאים: