Benutzerdefinierte App-Berechtigung festlegen

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

Hintergrund

Android ist ein privilegiertes Betriebssystem, in dem jede App mit einer eigenen Systemidentität ausgeführt wird (Linux-Nutzer-ID und -Gruppen-ID). Teile des Systems sind ebenfalls in verschiedene Identitäten unterteilt. Dadurch isoliert Linux Apps voneinander und vom System.

Anwendungen können ihre Funktionalität anderen Anwendungen zur Verfügung stellen, indem sie Berechtigungen definieren, die andere Apps anfordern können. Sie können auch Berechtigungen definieren, die automatisch anderen Apps zur Verfügung gestellt werden, die mit demselben Zertifikat signiert sind.

App-Signatur

Alle APKs müssen mit einem Zertifikat signiert sein, dessen privater Schlüssel vom Entwickler gehört. Das Zertifikat muss nicht von einer Zertifizierungsstelle signiert werden. Es ist zulässig und üblich, dass Android-Apps selbst signierte Zertifikate verwenden. Zertifikate in Android dienen dazu, App-Entwickler voneinander zu unterscheiden. Dadurch kann das System Apps Zugriff auf Berechtigungen auf Signaturebene gewähren oder verweigern und die Anfrage einer App zur Erteilung der gleichen Linux-Identität wie eine andere App gewähren oder ablehnen.

Signaturberechtigungen nach der Herstellung des Geräts erteilen

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

Sie können das Attribut knownCerts deklarieren und das Flag knownSigner im Attribut protectionLevel Ihrer App für eine bestimmte Berechtigung auf Signaturebene verwenden. Anschließend erteilt das System einer anfragenden App diese Berechtigung, wenn ein Unterzeichner in der Signatur 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 die Apps bei Herstellung und Versand 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 Dauer der 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 Sicherheitserzwingung 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.

Berechtigungen definieren und erzwingen

Wenn Sie Ihre eigenen Berechtigungen erzwingen möchten, müssen Sie diese zuerst in Ihrer 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 als Präfix hinzuzufügen. Verwenden Sie eine Reverse-Domain-Benennung, gefolgt von .permission. und einer Beschreibung der Funktion, die die Berechtigung darstellt, in einem Großbuchstaben SNAKE_CASE. Beispiel: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Wenn Sie dieser Empfehlung folgen, vermeiden Sie Namenskonflikte und helfen, den Inhaber und die Absicht einer benutzerdefinierten Berechtigung klar zu 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 wie folgt 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 gibt dem System an, wie Nutzer über Apps informiert werden sollen, die die Berechtigung benötigen, oder welche Apps die Berechtigung haben dürfen, wie in der verlinkten Dokumentation beschrieben.

Das Attribut android:permissionGroup ist optional und dient nur dazu, dem Nutzer die Berechtigungen des Systems anzuzeigen. In den meisten Fällen legen Sie dafür eine Standardsystemgruppe fest, die in android.Manifest.permission_group aufgeführt ist. Sie können eine Gruppe jedoch auch selbst definieren, wie im folgenden Abschnitt beschrieben. Wir empfehlen die Verwendung einer vorhandenen Gruppe, da dies die Benutzeroberfläche für Berechtigungen vereinfacht, die dem Nutzer angezeigt wird.

Sie müssen sowohl ein Label als auch eine Beschreibung für die Berechtigung 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 und enthält einige Wörter, die die Hauptfunktion beschreiben, die durch die Berechtigung geschützt wird. Die Beschreibung besteht aus einigen Sätzen, in denen beschrieben wird, was die Berechtigung einem Inhaber tun lässt. Unsere Konvention besteht aus einer Beschreibung in zwei Sätzen, wobei der erste Satz die Berechtigung beschreibt und der zweite Satz den Nutzer vor den Problemen warnt, die auftreten können, wenn eine App die Berechtigung erhält.

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, können Sie das Attribut android:permissionGroup verwenden, um dem System dabei zu helfen, Berechtigungen für den Nutzer 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 eine 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. Mit dem Element <permission-group> werden nicht die Berechtigungen angegeben, die zur Gruppe gehören. Es gibt der Gruppe aber einen Namen.

Sie können der Gruppe eine Berechtigung hinzufügen, 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.

Empfehlungen für benutzerdefinierte Berechtigungen

Mit <uses-permission>-Elementen kannst du benutzerdefinierte Berechtigungen für deine Apps definieren und von anderen Apps benutzerdefinierte Berechtigungen anfordern. Prüfen Sie jedoch sorgfältig, ob dies wirklich erforderlich ist.

  • Wenn Sie eine Suite von Anwendungen entwerfen, die einander Funktionen zur Verfügung stellen, sollten Sie die Anwendungen so gestalten, dass jede Berechtigung nur einmal definiert wird. Das müssen Sie tun, wenn nicht alle Anwendungen mit demselben Zertifikat signiert sind. Auch wenn alle Apps 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 möglicherweise vermeiden, benutzerdefinierte Berechtigungen durch Signaturprüfungen zu definieren. Stellt eine Ihrer Anwendungen eine Anfrage an eine andere Ihrer Anwendungen, kann die zweite Anwendung prüfen, ob beide Anwendungen mit demselben Zertifikat signiert sind, bevor sie der Anfrage nachkommt.

Wenn eine benutzerdefinierte Berechtigung erforderlich ist, sollten Sie sich überlegen, ob nur Anwendungen, die vom selben Entwickler signiert wurden wie die Anwendung, die die Berechtigungsprüfung durchführt, darauf zugreifen müssen. Dies ist beispielsweise der Fall, wenn eine sichere Kommunikation zwischen zwei Anwendungen desselben Entwicklers implementiert wird. In diesem Fall empfehlen wir die Verwendung von Signaturberechtigungen. Signaturberechtigungen sind für den Nutzer transparent und vermeiden vom Nutzer bestätigte Berechtigungen, die für Nutzer verwirrend sein können.

Weiterlesen über:

<uses-permission>
API-Referenz für das Manifest-Tag, das die erforderlichen Systemberechtigungen deiner App angibt.

Folgendes könnte Sie auch interessieren:

Sicherheit bei Android – Übersicht
Eine ausführliche Diskussion über das Sicherheitsmodell der Android-Plattform.