CheckPermission: примеры (JAVA)
checkPermission(Permission perm): voidОбщее описание метода checkPermission
В экосистеме Java под именем checkPermission встречается несколько методов, предназначенных для проверки прав доступа. Основные варианты расположены в классах SecurityManager, java.security.AccessController, а также в Android API - Context.checkPermission и PackageManager.checkPermission. Назначение одинаково в семантике: установить, предоставлено ли конкретное право (permission) для потока, процесса или пакета, и в зависимости от реализации вернуть код результата или бросить исключение.
Краткое сравнение по сигнатурам и поведению:
void SecurityManager.checkPermission(Permission perm)- классический метод, проверяющий разрешение для текущего контекста безопасности. При отсутствии права бросаетSecurityException. Возвращаемого значения нет.void AccessController.checkPermission(Permission perm)- проверка в рамках механизма контроля доступа. При отсутствии права бросаетAccessControlException.int Context.checkPermission(String permission, int pid, int uid)(Android) - возвращаетPackageManager.PERMISSION_GRANTEDилиPackageManager.PERMISSION_DENIEDв зависимости от наличия разрешения у указанного процесса/пользователя.int PackageManager.checkPermission(String permName, String pkgName)(Android) - проверяет, присвоено ли приложению с пакетом pkgName указанное разрешение. Возвращает те же константы, что и выше.
Параметры и возвращаемые значения
- Permission perm (java.security.Permission) - объект, описывающий ресурс и права (например,
new FilePermission("/tmp/*", "read")). Методы в ядре Java используют этот объект и бросают исключение при нарушении. - String permission (Android) - имя разрешения из манифеста или константа из
android.Manifest.permission. - int pid, int uid (Android Context.checkPermission) - идентификатор процесса и пользователя, для которого проверяется право. Часто используются
Process.myPid()иProcess.myUid()для проверки для текущего процесса. - String pkgName (PackageManager.checkPermission) - имя пакета приложения, для которого выполняется проверка.
- Возвращаемые значения для Android:
PackageManager.PERMISSION_GRANTED(обычно 0) при наличии права иPackageManager.PERMISSION_DENIEDпри его отсутствии. - Возвращаемые значения для Java core: отсутствие значения, вместо этого используется возбуждение исключения (
SecurityExceptionилиAccessControlException).
Поведение может зависеть от установленной Policy (java.security.Policy) и текущего менеджера безопасности. В Android дополнительно учитывается модель runtime-пермишнов (начиная с Android 6.0) и контекст выполнения приложения.
Краткие примеры использования
1. SecurityManager.checkPermission - пример с выбросом исключения:
import java.security.*;
import java.io.*;
public class SecCheck {
public static void main(String[] args) {
SecurityManager sm = System.getSecurityManager();
Permission perm = new FilePermission("/tmp/secret.txt", "read");
try {
if (sm != null) sm.checkPermission(perm);
System.out.println("allowed");
} catch (SecurityException e) {
System.out.println("denied: " + e.getMessage());
}
}
}
denied: access denied (java.io.FilePermission /tmp/secret.txt read)
2. AccessController.checkPermission - проверка в привилегированном блоке:
import java.security.*;
public class ACCheck {
public static void main(String[] args) {
Permission perm = new RuntimePermission("exitVM");
try {
AccessController.checkPermission(perm);
System.out.println("exitVM permitted");
} catch (AccessControlException e) {
System.out.println("not permitted: " + e.getPermission());
}
}
}
not permitted: (java.lang.RuntimePermission exitVM)
3. Android: Context.checkPermission для текущего процесса:
// внутри Activity или Context
int res = checkPermission(android.Manifest.permission.CAMERA,
android.os.Process.myPid(),
android.os.Process.myUid());
if (res == android.content.pm.PackageManager.PERMISSION_GRANTED) {
System.out.println("granted");
} else {
System.out.println("denied");
}
denied
4. Android: PackageManager.checkPermission для другого пакета:
PackageManager pm = getPackageManager();
int r = pm.checkPermission(android.Manifest.permission.INTERNET, "com.example.app");
System.out.println(r == PackageManager.PERMISSION_GRANTED ? "granted" : "denied");
granted
Похожие методы в Java и их особенности
- AccessController.checkPermission - альтернатива SecurityManager; используется в контексте менеджера доступа на уровне класслоадеров и доменов защиты. Возбуждает AccessControlException.
- Policy.getPolicy().implies(ProtectionDomain, Permission) - позволяет напрямую спросить, подразумевает ли текущая политика конкретное разрешение для домена защиты.
- Permission.implies - метод у конкретных Permission-классов для локальной логики сопоставления (например, FilePermission). Полезно для пользовательских реализаций прав.
Рекомендации по использованию: если требуется стандартная проверка в рантайме для класса/потока, чаще применяется AccessController в новых модулях; для совместимости с существующим кодом может использоваться SecurityManager, однако он помечен как устаревающий. Для политик на уровне приложения и тестирования выгодно использовать Policy и Permission.implies.
Эквиваленты в других языках и их отличия
- Python: os.access(path, mode) - проверка прав доступа к файлу на уровне ОС; возвращает булево. Пример:
import os print(os.access('/tmp/secret.txt', os.R_OK))False
Отличие: проверка файловых прав, не модель прав приложения/пользователя Java. - JavaScript (браузер): navigator.permissions.query({name: 'geolocation'}) - асинхронная проверка разрешения. Пример:
navigator.permissions.query({name:'geolocation'}).then(p => console.log(p.state));"prompt"
Отличие: модель браузерных разрешений, асинхронная и декларативная. - Node.js: fs.access(path, fs.constants.R_OK, cb) - проверка доступности файла. Возвращает ошибку в колбэке или null. Отличие - файловая проверка, не ролевая модель.
- PHP: is_readable(), is_writable() - простые проверки прав на файлы. Для ролей приложений используются фреймворки и проверки прав в БД.
- C#/.NET: PrincipalPermission.Demand() или WindowsPrincipal.IsInRole() - проверка прав пользователя/роли. Пример:
using System.Security.Principal; Console.WriteLine(new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole("Administrators"));False
Отличие: встроенная модель ролей и декларативные разрешения, а не Permission-объекты Java. - Go: os.Stat + mode.Perm() или syscall.Access для проверки файловых прав. Пример:
import ("os"); fi, _ := os.Stat("/tmp/secret.txt"); fmt.Println(fi.Mode().Perm() & 0400 != 0)false
Отличие: OS-ориентированная проверка, отсутствие единой модели пермишенов для приложения. - Kotlin: использует те же API, что и Java, поэтому
checkPermissionприменяется идентично. - Lua: в чистом языке нет встроенной модели прав; проверка часто делегируется ОС или окружению (например, читать файл через io.open и проверять результат).
Типичные ошибки при использовании checkPermission
- Ожидание булевого результата от
SecurityManager.checkPermission. В действительности метод возвращаетvoidи при отсутствии права бросает исключение. Пример ошибки:SecurityManager sm = System.getSecurityManager(); if (sm.checkPermission(perm)) { ... } // компиляция не пройдётОшибка компиляции: incompatible types: unexpected return value
- Неправильное использование Android API: вызов
checkPermissionбез указания pid/uid для чужого процесса или ожидание, что метод заменяет механизм runtime-permissions. Пример:// неверно - проверяет не для текущего процесса int r = checkPermission(Manifest.permission.CAMERA, 0, 0);denied
- Игнорирование возможности null у
System.getSecurityManager(). При отсутствии менеджера безопасности вызов checkPermission у sm приведёт к NPE. Рекомендуется сначала проверить на null. - Смешение уровней: ожидание, что проверка файловых прав ОС эквивалентна проверке Java Permission. FilePermission и права ОС могут не совпадать в контейнеризованных средах.
Изменения и эволюция поведения
- SecurityManager помечен как устаревший (deprecated for removal) начиная с Java 17 (JEP 411). Это влияет на применение
SecurityManager.checkPermissionв новых версиях JDK: рекомендуется планировать миграцию от модели SecurityManager к другим механизмам контроля доступа. - Механизм
AccessControllerи модельPolicyостаются в платформе, но для новых приложений чаще применяются специализированные средства безопасности (контейнеры, ограниченные рантаймы). - В Android возникла модель runtime-permissions начиная с Android 6.0 (Marshmallow). До этого достаточно было декларации в манифесте; теперь для определённых опасных разрешений требуется динамический запрос у пользователя и проверка через
checkSelfPermission/requestPermissions.
Расширенные и редкие варианты использования
1. Создание собственного Permission и проверка через AccessController
import java.security.*;
public final class MyPermission extends Permission {
public MyPermission(String name) { super(name); }
public boolean implies(Permission p) { return equals(p); }
public boolean equals(Object o) { return (o instanceof MyPermission) && getName().equals(((MyPermission)o).getName()); }
public int hashCode() { return getName().hashCode(); }
public PermissionCollection newPermissionCollection() { return null; }
}
// использование
try {
AccessController.checkPermission(new MyPermission("useSpecialFeature"));
System.out.println("ok");
} catch (AccessControlException e) {
System.out.println("forbidden");
}
forbidden
Пояснение: собственные Permission позволяют описать специфичные для приложения права и использовать инфраструктуру AccessController/Policy.
2. DoPrivileged в сочетании с проверкой прав
Permission perm = new RuntimePermission("getClassLoader");
try {
AccessController.doPrivileged((PrivilegedAction) () -> {
// локальная привилегированная операция
return null;
}, new AccessControlContext(new ProtectionDomain[]{new ProtectionDomain(null, new Permissions())}));
AccessController.checkPermission(perm);
System.out.println("allowed within privileged context");
} catch (AccessControlException e) {
System.out.println("denied");
}
denied
Пояснение: применение doPrivileged влияет на стек проверки и позволяет выполнять действия под повышенными привилегиями при корректной конфигурации политик.
3. Android: проверка нескольких разрешений и запрос отсутствующих у пользователя
String[] perms = {Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO};
List<String> miss = new ArrayList<>();
for (String p: perms) {
if (checkSelfPermission(p) != PackageManager.PERMISSION_GRANTED) miss.add(p);
}
if (!miss.isEmpty()) {
requestPermissions(miss.toArray(new String[0]), 123);
} else {
System.out.println("all granted");
}
all granted
Пояснение: на Android часто требуется одновременно проверять набор разрешений и запрашивать у пользователя отсутствующие.
4. Проверка разрешений для другого приложения (Android) - сценарий для системных компонентов или менеджеров
PackageManager pm = getPackageManager();
int r = pm.checkPermission(Manifest.permission.SEND_SMS, "com.example.client");
if (r == PackageManager.PERMISSION_GRANTED) {
// разрешено отправлять SMS
}
(зависит от настроек на устройстве)
Пояснение: проверка прав другого пакета требует прав доступа у проверяющего процесса и актуальна для сервисов управления правами, антивирусов и MDM-решений.