بهبود امنیت با خط‌مشی‌های مدیریت دستگاه

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

از Android نسخه ۲.۲ (سطح میانای برنامه‌سازی کاربردی ۸)، پلاتفرم Android قابلیت‌های مدیریت دستگاه در سطح سیستم را ازطریق میاناهای برنامه‌سازی کاربردی «مدیریت دستگاه» ارائه می‌دهد.

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

خط‌مشی‌تان را تعریف و اعلام کنید

ابتدا باید انواع خط‌مشی‌هایی را که می‌خواهید در سطح عملکردی پشتیبانی کنید تعریف کنید. خط‌مشی‌ها ممکن است شامل قدرت گذرواژه قفل صفحه، زمان انقضا، رمزگذاری، و غیره باشد.

باید مجموعه خط‌مشی انتخاب‌شده را که توسط برنامه اجرا خواهد شد در فایل res/xml/device_admin.xml اعلام کنید. مانیفست Android باید به مجموعه خط‌مشی اعلام‌شده نیز ارجاع دهد.

هر خط‌مشی اعلام‌شده با تعدادی از روش‌های خط‌مشی دستگاه مرتبط در DevicePolicyManager مطابقت دارد (تعریف حداقل طول گذرواژه و حداقل تعداد نویسه‌های بزرگ دو نمونه هستند). اگر برنامه‌ای تلاش کند روش‌هایی را فراخوانی کند که خط‌مشی مربوط به آن‌ها در XML اعلام نشده باشد، این کار منجر به SecurityException در زمان اجرا خواهد شد. اجازه‌های دیگر، مثل force-lock، دردسترس هستند اگر برنامه قصد داشته باشد انواع دیگر خط‌مشی را مدیریت کند. همان‌طور که بعداً خواهید دید، به‌عنوان بخشی از فرایند فعال‌سازی سرپرست دستگاه، فهرست خط‌مشی‌های اعلام‌شده در صفحه سیستم به کاربر ارائه خواهد شد.

قطعه کد زیر خط‌مشی محدودیت گذرواژه را در res/xml/device_admin.xml اعلام می‌کند:

<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <limit-password />
    </uses-policies>
</device-admin>

XML اظهارنامه خط‌مشی ارجاع‌شده در مانیفست Android:

<receiver android:name=".Policy$PolicyAdmin"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data android:name="android.app.device_admin"
        android:resource="@xml/device_admin" />
    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
    </intent-filter>
</receiver>

ایجاد گیرنده مدیریت دستگاه

گیرنده رویداد ثبت‌شده «مدیریت دستگاه» ایجاد کنید که از رویدادهای مربوط به خط‌مشی‌هایی که اعلام کرده‌اید پشتیبانی می‌کنید مطلع می‌شود. برنامه می‌تواند به‌طور انتخابی روش‌های فراخوانی را لغو کند.

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

برای اینکه گیرنده رویداد ثبت‌شده کار کند، حتماً آن را در مانیفست Android ثبت کنید، همان‌طور که در قطعه کد بالا نشان داده شده است.

کاتلین

class PolicyAdmin : DeviceAdminReceiver() {

    override fun onDisabled(context: Context, intent: Intent) {
        // Called when the app is about to be deactivated as a device administrator.
        // Deletes previously stored password policy.
        super.onDisabled(context, intent)
        context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE).edit().apply {
            clear()
            apply()
        }
    }
}

جاوا

public static class PolicyAdmin extends DeviceAdminReceiver {

    @Override
    public void onDisabled(Context context, Intent intent) {
        // Called when the app is about to be deactivated as a device administrator.
        // Deletes previously stored password policy.
        super.onDisabled(context, intent);
        SharedPreferences prefs = context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE);
        prefs.edit().clear().commit();
    }
}

فعال کردن سرپرست دستگاه

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

شکل ۱. صفحه فعال‌سازی کاربر که در آن می‌توانید شرحی از خط‌مشی‌های دستگاهتان ارائه دهید.

کاتلین

if (!policy.isAdminActive()) {

    val activateDeviceAdminIntent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)

    activateDeviceAdminIntent.putExtra(
            DevicePolicyManager.EXTRA_DEVICE_ADMIN,
            policy.getPolicyAdmin()
    )

    // It is good practice to include the optional explanation text to
    // explain to user why the application is requesting to be a device
    // administrator. The system will display this message on the activation
    // screen.
    activateDeviceAdminIntent.putExtra(
            DevicePolicyManager.EXTRA_ADD_EXPLANATION,
            resources.getString(R.string.device_admin_activation_message)
    )

    startActivityForResult(activateDeviceAdminIntent, REQ_ACTIVATE_DEVICE_ADMIN)
}

جاوا

if (!policy.isAdminActive()) {

    Intent activateDeviceAdminIntent =
        new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);

    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_DEVICE_ADMIN,
        policy.getPolicyAdmin());

    // It is good practice to include the optional explanation text to
    // explain to user why the application is requesting to be a device
    // administrator. The system will display this message on the activation
    // screen.
    activateDeviceAdminIntent.putExtra(
        DevicePolicyManager.EXTRA_ADD_EXPLANATION,
        getResources().getString(R.string.device_admin_activation_message));

    startActivityForResult(activateDeviceAdminIntent,
        REQ_ACTIVATE_DEVICE_ADMIN);
}

اگر کاربر «فعال کردن» را انتخاب کند، برنامه سرپرست دستگاه می‌شود و می‌تواند پیکربندی و اجرای خط‌مشی را آغاز کند.

همچنین برنامه باید برای رسیدگی به موقعیت‌های عقب‌نشینی که کاربر با زدن دکمه «لغو»، کلید «برگشت»، یا کلید «صفحه اصلی» فرایند فعال‌سازی را رها می‌کند آماده باشد. بنابراین، onResume() در «فعالیت راه‌اندازی خط‌مشی» باید منطقی داشته باشد تا شرایط را دوباره ارزیابی کند و درصورت نیاز، گزینه «فعال‌سازی سرپرست دستگاه» را به کاربر ارائه دهد.

پیاده‌سازی کنترل‌کننده خط‌مشی دستگاه

پس‌از فعال شدن موفقیت‌آمیز سرپرست دستگاه، برنامه سپس «مدیر خط‌مشی دستگاه» را با خط‌مشی درخواست‌شده پیکربندی می‌کند. به‌خاطر داشته باشید که با هر نسخه پخش، خط‌مشی‌های جدیدی به Android اضافه می‌شود. اگر از خط‌مشی‌های جدید استفاده می‌کنید و درعین‌حال از نسخه‌های قدیمی‌تر پلاتفرم پشتیبانی می‌کنید، انجام بررسی‌های نسخه در برنامه‌تان مناسب است. برای مثال، خط‌مشی «حداقل حروف بزرگ گذرواژه» فقط با سطح میانای برنامه‌سازی کاربردی ۱۱ (Honeycomb) و بالاتر دردسترس است. کد زیر نشان می‌دهد که چگونه می‌توانید نسخه را در زمان اجرا بررسی کنید.

کاتلین

private lateinit var dpm: DevicePolicyManager
private lateinit var policyAdmin: ComponentName

dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
policyAdmin = ComponentName(context, PolicyAdmin::class.java)

dpm.apply {
    setPasswordQuality(policyAdmin, PASSWORD_QUALITY_VALUES[passwordQuality])
    setPasswordMinimumLength(policyAdmin, passwordLength)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        setPasswordMinimumUpperCase(policyAdmin, passwordMinUpperCase)
    }
}

جاوا

DevicePolicyManager dpm = (DevicePolicyManager)
        context.getSystemService(Context.DEVICE_POLICY_SERVICE);
ComponentName policyAdmin = new ComponentName(context, PolicyAdmin.class);

dpm.setPasswordQuality(policyAdmin, PASSWORD_QUALITY_VALUES[passwordQuality]);
dpm.setPasswordMinimumLength(policyAdmin, passwordLength);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    dpm.setPasswordMinimumUpperCase(policyAdmin, passwordMinUpperCase);
}

در این مرحله، برنامه می‌تواند خط‌مشی را اجرا کند. درحالی‌که برنامه به گذرواژه واقعی قفل صفحه استفاده‌شده دسترسی ندارد، ازطریق Device Policy Manager API می‌تواند تعیین کند که آیا گذرواژه موجود خط‌مشی موردنیاز را برآورده می‌کند یا نه. اگر مشخص شود که گذرواژه قفل صفحه موجود کافی نیست، API مدیریت دستگاه به‌طور خودکار اقدام اصلاحی انجام نمی‌دهد. مسئولیت راه‌اندازی صریح صفحه تغییر گذرواژه سیستم در برنامه «تنظیمات» برعهده برنامه است. برای مثال:

کاتلین

if (!dpm.isActivePasswordSufficient) {
    // Triggers password change screen in Settings.
    Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD).also { intent ->
        startActivity(intent)
    }
}

جاوا

if (!dpm.isActivePasswordSufficient()) {
    ...
    // Triggers password change screen in Settings.
    Intent intent =
        new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
    startActivity(intent);
}

معمولاً کاربر می‌تواند یکی از سازوکارهای قفل موجود را انتخاب کند، مانند «هیچ‌کدام»، «الگو»، «پین» (عددی)، یا «گذرواژه» (حرفی-عددی). وقتی خط‌مشی گذرواژه پیکربندی می‌شود، آن نوع گذرواژه‌هایی که ضعیف‌تر از گذرواژه‌های تعریف‌شده در خط‌مشی هستند غیرفعال می‌شوند. برای مثال، اگر کیفیت گذرواژه «عددی» پیکربندی شده باشد، کاربر فقط می‌تواند پین (عددی) یا گذرواژه (حرفی-عددی) را انتخاب کند.

وقتی دستگاه با راه‌اندازی گذرواژه قفل صفحه مناسب به‌درستی ایمن شد، برنامه اجازه دسترسی به محتوای ایمن‌شده را می‌دهد.

کاتلین

when {
    !dpm.isAdminActive(policyAdmin) -> {
        // Activates device administrator.
        ...
    }
    !dpm.isActivePasswordSufficient -> {
        // Launches password set-up screen in Settings.
        ...
    }
    else -> {
        // Grants access to secure content.
        ...
        startActivity(Intent(context, SecureActivity::class.java))
    }
}

جاوا

if (!dpm.isAdminActive(..)) {
    // Activates device administrator.
    ...
} else if (!dpm.isActivePasswordSufficient()) {
    // Launches password set-up screen in Settings.
    ...
} else {
    // Grants access to secure content.
    ...
    startActivity(new Intent(context, SecureActivity.class));
}