Сталкивались ли вы с конфликтами или проблемами, связанными с системой разрешений (Permissions) в приложениях?

«Сталкивались ли вы с конфликтами или проблемами, связанными с системой разрешений (Permissions) в приложениях?» — вопрос из категории Тестирование безопасности, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, конфликты и неочевидные проблемы с разрешениями — частый источник дефектов, особенно в мобильных и многопользовательских веб-приложениях.

Типичные сценарии проблем:

  1. Конфликт разрешений: Когда одно разрешение (явно или через роль) запрещает действие, которое другое разрешает. Система должна иметь четкий порядок приоритета (например, "Deny" перекрывает "Allow").
  2. Неправильная область видимости (Scope): В Android с API 23+ (targetSdkVersion >= 23) разрешения на доступ к хранилищу (READ_EXTERNAL_STORAGE) требуют runtime-запроса. Если приложение запрашивает только WRITE_EXTERNAL_STORAGE, оно может не получить доступ на чтение файлов, созданных другими приложениями.
  3. Устаревшие модели доступа: На Android 10+ (API 29) введена Scoped Storage. Приложения, использующие устаревший неограниченный доступ к общему хранилищу, могут столкнуться с ошибками "Permission denied" после обновления targetSdkVersion.

Пример кода для корректного запроса runtime-разрешений в Android:

// Проверяем, есть ли уже разрешение
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
        != PackageManager.PERMISSION_GRANTED) {
    // Разрешение отсутствует, запрашиваем его
    ActivityCompat.requestPermissions(this,
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
            REQUEST_CODE_READ_STORAGE // Уникальный код запроса
    )
} else {
    // Разрешение уже предоставлено, выполняем операцию
    loadFileFromStorage()
}

// Обработка ответа пользователя
override fun onRequestPermissionsResult(requestCode: Int,
                                        permissions: Array<out String>,
                                        grantResults: IntArray) {
    when (requestCode) {
        REQUEST_CODE_READ_STORAGE -> {
            if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Пользователь разрешил
                loadFileFromStorage()
            } else {
                // Пользователь отказал, объясняем необходимость
                showPermissionRationale()
            }
        }
        // Обработка других кодов запроса...
    }
}

Тестирование таких сценариев включает: проверку граничных состояний (разрешение выдано/отклонено/отозвано), работу в "sandbox" (Scoped Storage), а также анализ манифеста приложения на предмет избыточных или конфликтующих разрешений.