Benutzerdefinierte App-Berechtigung festlegen

In diesem Dokument wird beschrieben, wie App-Entwickler mit den von Android bereitgestellten Sicherheitsfunktionen ihre eigenen Berechtigungen definieren können. Durch das Definieren benutzerdefinierter Berechtigungen kann eine Anwendung ihre Ressourcen und Funktionen für andere Anwendungen freigeben. Weitere Informationen zu Berechtigungen finden Sie in der Berechtigungsübersicht.

Hintergrund

Android ist ein Betriebssystem mit mehreren Berechtigungen, wobei jede App mit einer eigenen Systemidentität ausgeführt wird (Linux-Nutzer-ID und ‐Gruppen-ID). Teile des Systems werden ebenfalls in verschiedene Identitäten unterteilt. Auf diese Weise isoliert Linux Apps voneinander und vom System.

Apps können ihre Funktionen für andere Apps verfügbar machen, indem sie Berechtigungen definieren, die andere Apps anfordern können. Sie können auch Berechtigungen definieren, die automatisch für andere Anwendungen verfügbar gemacht werden, die mit demselben Zertifikat signiert sind.

App-Signatur

Alle APKs müssen mit einem Zertifikat signiert sein, dessen privater Schlüssel vom Entwickler verwaltet wird. Das Zertifikat muss nicht von einer Zertifizierungsstelle signiert werden. Die Verwendung selbst signierter Zertifikate ist in der Regel für Android-Apps zulässig. Der Zweck von Zertifikaten in Android besteht darin, App-Entwickler zu unterscheiden. So kann das System Anwendungen den Zugriff auf Berechtigungen auf Signaturebene gewähren oder verweigern und die Anfrage einer Anwendung nach der Erteilung der gleichen Linux-Identität wie eine andere Anwendung gewähren oder ablehnen.

Signaturberechtigungen nach der Herstellung des Geräts erteilen

Ab Android 12 (API-Level 31) kannst du mit dem Attribut knownCerts für Berechtigungen auf Signaturebene auf die Digests bekannter Signaturzertifikate zum Zeitpunkt der Deklaration verweisen.

Du kannst das Attribut knownCerts deklarieren und das Flag knownSigner im Attribut protectionLevel deiner App für eine bestimmte Berechtigung auf Signaturebene verwenden. Dann erteilt das System diese Berechtigung einer anfragenden App, wenn ein Unterzeichner in der Signaturherkunft der anfragenden App, einschließlich des aktuellen Unterzeichners, mit einem der Digests übereinstimmt, die mit der Berechtigung im Attribut knownCerts deklariert sind.

Mit dem Flag knownSigner können Geräte und Apps anderen Apps Signaturberechtigungen erteilen, ohne dass diese Apps bei der Herstellung und Lieferung des Geräts signiert werden müssen.

Nutzer-IDs und Dateizugriff

Bei der Installation weist Android jedem Paket eine eigene Linux-Nutzer-ID zu. Die Identität bleibt für die Lebensdauer des Pakets auf diesem Gerät konstant. Auf einem anderen Gerät kann dasselbe Paket eine andere UID haben. Wichtig ist, dass jedes Paket auf einem bestimmten Gerät eine eigene UID hat.

Da die Sicherheitsdurchsetzung auf Prozessebene erfolgt, kann der Code zweier Pakete normalerweise nicht im selben Prozess ausgeführt werden, da sie als unterschiedliche Linux-Nutzer ausgeführt werden müssen.

Alle von einer Anwendung gespeicherten Daten werden der Nutzer-ID dieser Anwendung zugewiesen und sind normalerweise für andere Pakete nicht zugänglich.

Weitere Informationen zum Sicherheitsmodell von Android findest du unter Android-Sicherheit – Übersicht.

Berechtigungen definieren und erzwingen

Wenn du deine eigenen Berechtigungen erzwingen möchtest, musst du sie zuerst in deinem AndroidManifest.xml mit einem oder mehreren <permission>-Elementen deklarieren.

Namenskonvention

Das System lässt nicht zu, dass mehrere Pakete eine Berechtigung mit demselben Namen deklarieren, es sei denn, alle Pakete sind mit demselben Zertifikat signiert. Wenn ein Paket eine Berechtigung deklariert, erlaubt das System dem Nutzer auch nicht, andere Pakete mit demselben Berechtigungsnamen zu installieren, es sei denn, diese Pakete sind mit demselben Zertifikat wie das erste Paket signiert.

Wir empfehlen, Berechtigungen den Paketnamen einer App voranzustellen. Dazu verwenden Sie eine Namensgebung im umgekehrten Domainstil, gefolgt von .permission. und einer Beschreibung der Funktion, die die Berechtigung repräsentiert, in Großbuchstaben SNAKE_CASE. Beispiel: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Wenn Sie dieser Empfehlung folgen, vermeiden Sie Namenskonflikte und können den Inhaber und die Absicht einer benutzerdefinierten Berechtigung eindeutig identifizieren.

Beispiel

Beispielsweise kann eine App, die steuern muss, welche anderen Apps eine ihrer Aktivitäten starten können, eine Berechtigung für diesen Vorgang so deklarieren:

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapp" >
    
    <permission
      android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
      android:label="@string/permlab_deadlyActivity"
      android:description="@string/permdesc_deadlyActivity"
      android:permissionGroup="android.permission-group.COST_MONEY"
      android:protectionLevel="dangerous" />
    ...
</manifest>

Das Attribut protectionLevel ist erforderlich und teilt dem System mit, wie Nutzer über Apps informiert werden sollen, für die eine Berechtigung erforderlich ist oder welche Apps die Berechtigung haben können, wie in der verlinkten Dokumentation beschrieben.

Das Attribut android:permissionGroup ist optional und wird nur verwendet, damit das System dem Nutzer Berechtigungen anzeigen kann. In den meisten Fällen legen Sie dafür eine Standardsystemgruppe fest (in android.Manifest.permission_group aufgeführt). Sie können die Gruppe aber auch selbst definieren, wie im folgenden Abschnitt beschrieben. Wir empfehlen die Verwendung einer vorhandenen Gruppe, da dies die dem Nutzer angezeigte Berechtigungs-UI dadurch vereinfacht.

Sie müssen für die Berechtigung sowohl ein Label als auch eine Beschreibung angeben. Dies sind Stringressourcen, die der Nutzer sehen kann, wenn er eine Liste von Berechtigungen (android:label) oder Details zu einer einzelnen Berechtigung (android:description) aufruft. Das Label ist kurz: einige Wörter, die die Hauptfunktionalität beschreiben, die durch die Berechtigung geschützt wird. Die Beschreibung besteht aus mehreren Sätzen, die beschreiben, was der Inhaber mit der Berechtigung tun kann. Unsere Konvention besteht aus einer Beschreibung in zwei Sätzen, bei der der erste Satz die Berechtigung beschreibt, und der zweite Satz warnt den Nutzer vor Problemen, die bei Erteilung der Berechtigung einer App möglicherweise schiefgehen können.

Hier sehen Sie ein Beispiel für ein Label und eine Beschreibung für die Berechtigung CALL_PHONE:

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call non-emergency
phone numbers without your intervention. Malicious apps may cause unexpected
calls on your phone bill.</string>

Berechtigungsgruppe erstellen

Wie im vorherigen Abschnitt gezeigt, kannst du das Attribut android:permissionGroup verwenden, um dem System dabei zu helfen, dem Nutzer Berechtigungen zu beschreiben. In den meisten Fällen legen Sie dafür eine Standardsystemgruppe fest, die in android.Manifest.permission_group aufgeführt ist. Sie können aber auch Ihre eigene Gruppe mit <permission-group> definieren.

Das Element <permission-group> definiert ein Label für eine Reihe von Berechtigungen – sowohl die im Manifest mit <permission>-Elementen deklarierten als auch die an anderer Stelle deklarierten Berechtigungen. Dies wirkt sich nur darauf aus, wie die Berechtigungen gruppiert werden, wenn sie dem Nutzer angezeigt werden. Das Element <permission-group> gibt nicht die Berechtigungen an, die zur Gruppe gehören, gibt der Gruppe aber einen Namen.

Sie können der Gruppe eine Berechtigung zuweisen, indem Sie den Gruppennamen dem Attribut permissionGroup des <permission>-Elements zuweisen.

Das Element <permission-tree> deklariert einen Namespace für eine Gruppe von Berechtigungen, die im Code definiert sind.

Benutzerdefinierte Empfehlungen für Berechtigungen

Du kannst benutzerdefinierte Berechtigungen für deine Apps und benutzerdefinierte Berechtigungen von anderen Apps durch das Definieren von <uses-permission>-Elementen festlegen. Sie sollten jedoch sorgfältig abwägen, ob dies erforderlich ist.

  • Wenn Sie eine Suite von Apps entwerfen, die sich gegenseitig Funktionen bereitstellen, sollten Sie die Anwendungen so gestalten, dass jede Berechtigung nur einmal definiert ist. Dieser Schritt ist erforderlich, wenn nicht alle Apps mit demselben Zertifikat signiert sind. Auch wenn die Apps alle mit demselben Zertifikat signiert sind, empfiehlt es sich, jede Berechtigung nur einmal zu definieren.
  • Wenn die Funktion nur für Anwendungen verfügbar ist, die mit derselben Signatur wie die bereitstellende Anwendung signiert sind, können Sie es möglicherweise vermeiden, benutzerdefinierte Berechtigungen mithilfe von Signaturprüfungen zu definieren. Wenn eine Ihrer Apps eine Anfrage an eine andere Ihrer Apps sendet, kann die zweite App prüfen, ob beide Apps mit demselben Zertifikat signiert sind, bevor sie der Anfrage nachkommt.

Wenn eine benutzerdefinierte Berechtigung erforderlich ist, prüfen Sie, ob nur Anwendungen, die von demselben Entwickler wie die Anwendung, die die Berechtigungsprüfung durchführt, signiert sind, z. B. bei der Implementierung einer sicheren Interprozesskommunikation zwischen zwei Anwendungen desselben Entwicklers. In diesem Fall empfehlen wir die Verwendung von Signaturberechtigungen. Signaturberechtigungen sind für den Nutzer transparent und enthalten keine vom Nutzer bestätigten Berechtigungen, die für Nutzer verwirrend sein können.

Lesen Sie weiter zu:

<uses-permission>
API-Referenz für das Manifest-Tag, mit dem die erforderlichen Systemberechtigungen für deine App deklariert sind

Das könnte Sie auch interessieren:

Android-Sicherheit – Übersicht
Eine ausführliche Diskussion zum Sicherheitsmodell der Android-Plattform.