Tăng cường bảo mật bằng các chính sách quản lý thiết bị

Ngừng sử dụng tính năng quản trị viên thiết bị. Một số chính sách quản trị đã được đánh dấu là không dùng nữa khi được quản trị viên thiết bị gọi. Để tìm hiểu thêm và xem các tuỳ chọn di chuyển, hãy xem bài viết Ngừng hỗ trợ quản trị viên thiết bị.

Kể từ Android 2.2 (API cấp 8), nền tảng Android cung cấp tính năng quản lý thiết bị ở cấp hệ thống thông qua API Quản trị thiết bị.

Trong bài học này, bạn sẽ tìm hiểu cách tạo một ứng dụng có khả năng nhận biết bảo mật để quản lý quyền truy cập vào nội dung của ứng dụng đó bằng cách thực thi các chính sách quản lý thiết bị. Cụ thể, ứng dụng có thể được định cấu hình để đảm bảo thiết lập một mật khẩu khoá màn hình có đủ độ mạnh trước khi hiển thị nội dung bị hạn chế cho người dùng.

Định nghĩa và khai báo chính sách

Trước tiên, bạn cần xác định các loại chính sách hỗ trợ ở cấp chức năng. Các chính sách có thể bao gồm độ mạnh mật khẩu khoá màn hình, thời gian chờ hết hạn, hoạt động mã hoá, v.v.

Bạn phải khai báo bộ chính sách đã chọn (sẽ được ứng dụng thực thi) trong tệp res/xml/device_admin.xml. Tệp kê khai Android cũng phải tham chiếu đến bộ chính sách đã khai báo.

Mỗi chính sách đã khai báo tương ứng với một số phương thức chính sách thiết bị có liên quan trong DevicePolicyManager (ví dụ: hai ví dụ xác định độ dài mật khẩu tối thiểu và số lượng ký tự viết hoa tối thiểu). Nếu một ứng dụng cố gắng gọi các phương thức có chính sách tương ứng không được khai báo trong XML, thì thao tác này sẽ dẫn đến SecurityException trong thời gian chạy. Các quyền khác, chẳng hạn như force-lock, có sẵn nếu ứng dụng có ý định quản lý các loại chính sách khác. Như bạn sẽ thấy sau, trong quá trình kích hoạt quản trị viên thiết bị, danh sách các chính sách đã khai báo sẽ hiển thị cho người dùng trên màn hình hệ thống.

Đoạn mã sau khai báo chính sách giới hạn mật khẩu trong 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 khai báo chính sách được tham chiếu trong tệp kê khai 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>

Tạo trình thu nhận quản trị thiết bị

Tạo broadcast receiver của Quản trị thiết bị để nhận thông báo về các sự kiện liên quan đến các chính sách mà bạn đã khai báo để hỗ trợ. Một ứng dụng có thể ghi đè một cách có chọn lọc các phương thức gọi lại.

Trong ứng dụng mẫu, Quản trị viên thiết bị, khi quản trị viên thiết bị bị người dùng huỷ kích hoạt, chính sách đã định cấu hình sẽ bị xoá khỏi lựa chọn ưu tiên dùng chung. Bạn nên cân nhắc triển khai logic kinh doanh liên quan đến trường hợp sử dụng của mình. Ví dụ: ứng dụng có thể thực hiện một số hành động để giảm thiểu rủi ro bảo mật bằng cách triển khai một số tổ hợp gồm xoá dữ liệu nhạy cảm trên thiết bị, tắt tính năng đồng bộ hoá từ xa, cảnh báo quản trị viên, v.v.

Để broadcast receiver hoạt động, hãy nhớ đăng ký broadcast receiver này trong tệp kê khai Android như minh hoạ trong đoạn mã trên.

Kotlin

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

Java

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

Kích hoạt quản trị viên thiết bị

Trước khi thực thi bất kỳ chính sách nào, người dùng cần kích hoạt ứng dụng với tư cách là quản trị viên thiết bị theo cách thủ công. Đoạn mã dưới đây minh hoạ cách kích hoạt hoạt động cài đặt mà người dùng có thể kích hoạt ứng dụng. Bạn nên bao gồm văn bản giải thích để làm nổi bật cho người dùng lý do ứng dụng yêu cầu trở thành quản trị viên thiết bị, bằng cách chỉ định phần bổ sung EXTRA_ADD_EXPLANATION trong ý định.

Hình 1. Màn hình kích hoạt người dùng, nơi bạn có thể cung cấp nội dung mô tả về các chính sách thiết bị của mình.

Kotlin

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

Java

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

Nếu người dùng chọn "Kích hoạt", ứng dụng sẽ trở thành quản trị viên thiết bị và có thể bắt đầu định cấu hình và thực thi chính sách.

Ứng dụng cũng cần được chuẩn bị để xử lý các tình huống đặt lại mà trong đó người dùng bỏ qua quy trình kích hoạt bằng cách nhấn nút Cancel (Huỷ), phím Back (Quay lại) hoặc phím Home (Màn hình chính). Do đó, onResume() trong Hoạt động thiết lập chính sách cần có logic để đánh giá lại điều kiện và hiển thị tuỳ chọn Kích hoạt quản trị viên thiết bị cho người dùng nếu cần.

Triển khai trình kiểm soát chính sách thiết bị

Sau khi quản trị viên thiết bị được kích hoạt thành công, ứng dụng sẽ định cấu hình Trình quản lý chính sách thiết bị bằng chính sách được yêu cầu. Xin lưu ý rằng các chính sách mới sẽ được thêm vào Android trong mỗi bản phát hành. Bạn nên kiểm tra phiên bản trong ứng dụng nếu sử dụng các chính sách mới trong khi vẫn hỗ trợ các phiên bản cũ của nền tảng. Ví dụ: chính sách Mật khẩu viết hoa tối thiểu chỉ áp dụng với API cấp 11 (Honeycomb) trở lên. Mã sau đây minh hoạ cách kiểm tra phiên bản trong thời gian chạy.

Kotlin

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

Java

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

Tại thời điểm này, ứng dụng có thể thực thi chính sách. Mặc dù ứng dụng không có quyền truy cập vào mật khẩu khoá màn hình thực tế được dùng, nhưng thông qua API Trình quản lý chính sách thiết bị, ứng dụng có thể xác định liệu mật khẩu hiện tại có đáp ứng chính sách bắt buộc hay không. Nếu thực tế cho thấy mật khẩu khoá màn hình hiện có là không đủ, thì API quản trị thiết bị sẽ không tự động khắc phục. Ứng dụng có trách nhiệm khởi chạy rõ ràng màn hình thay đổi mật khẩu hệ thống trong ứng dụng Cài đặt. Ví dụ:

Kotlin

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

Java

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

Thông thường, người dùng có thể chọn một trong các cơ chế khoá hiện có, chẳng hạn như Không có, Hình mở khoá, Mã PIN (số) hoặc Mật khẩu (chữ số). Khi bạn định cấu hình một chính sách mật khẩu, những loại mật khẩu yếu hơn các loại mật khẩu được xác định trong chính sách này sẽ bị tắt. Ví dụ: nếu chất lượng mật khẩu "Số" được định cấu hình, thì người dùng chỉ có thể chọn mật khẩu mã PIN (chữ số) hoặc mật khẩu Mật khẩu (chữ số).

Sau khi thiết bị được bảo vệ đúng cách bằng cách thiết lập một mật khẩu khoá màn hình phù hợp, ứng dụng sẽ cho phép truy cập vào nội dung được bảo mật.

Kotlin

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

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