Definiowanie niestandardowych uprawnień aplikacji

W tym dokumencie opisano, jak deweloperzy aplikacji mogą używać funkcji zabezpieczeń udostępnianych przez Androida do definiowania własnych uprawnień. Dzięki zdefiniowaniu uprawnień niestandardowych aplikacja może udostępniać swoje zasoby i możliwości innym aplikacjom. Więcej informacji o uprawnieniach znajdziesz w ich omówieniu.

Tło

Android to system operacyjny z podziałem uprawnień, w którym każda aplikacja działa z osobną tożsamością systemową (identyfikatorem użytkownika i identyfikatorem grupy w systemie Linux). Części systemu są też podzielone na odrębne tożsamości. Linux izoluje aplikacje od siebie i od systemu.

Aplikacje mogą udostępniać swoje funkcje innym aplikacjom, definiując uprawnienia, o które mogą prosić inne aplikacje. Mogą też definiować uprawnienia, które są automatycznie udostępniane innym aplikacjom podpisanym tym samym certyfikatem.

Podpisywanie aplikacji

Wszystkie pliki APK muszą być podpisane certyfikatem, którego klucz prywatny jest przechowywany przez dewelopera. Certyfikat nie musi być podpisany przez urząd certyfikacji. Aplikacje na Androida mogą używać certyfikatów podpisanych samodzielnie i jest to typowe rozwiązanie. Certyfikaty na Androidzie służą do odróżniania autorów aplikacji. Dzięki temu system może przyznawać aplikacjom uprawnienia na poziomie podpisu lub odmawiać im dostępu do tych uprawnień, a także przyznawać aplikacjom tę samą tożsamość Linuksa co innej aplikacji lub odrzucać takie żądania.

Przyznawanie uprawnień do podpisu po wyprodukowaniu urządzenia

Począwszy od Androida 12 (poziom interfejsu API 31), atrybut knownCerts uprawnień na poziomie podpisu umożliwia odwoływanie się do skrótów znanych certyfikatów podpisywania w momencie deklaracji.

Możesz zadeklarować atrybut knownCerts i użyć flagi knownSigner w atrybucie protectionLevel aplikacji w przypadku konkretnego uprawnienia na poziomie podpisu. Następnie system przyznaje to uprawnienie aplikacji, która o nie prosi, jeśli którykolwiek podpisujący w rodowodzie podpisywania aplikacji, w tym bieżący podpisujący, pasuje do jednego ze skrótów zadeklarowanych z uprawnieniem w atrybucie knownCerts.

Flaga knownSigner umożliwia urządzeniom i aplikacjom przyznawanie uprawnień do podpisu innym aplikacjom bez konieczności podpisywania aplikacji w momencie produkcji i wysyłki urządzenia.

Identyfikatory użytkowników i dostęp do plików

Podczas instalacji Android nadaje każdemu pakietowi odrębny identyfikator użytkownika w systemie Linux. Tożsamość pozostaje niezmienna przez cały okres istnienia pakietu na danym urządzeniu. Na innym urządzeniu ten sam pakiet może mieć inny identyfikator UID – ważne jest, aby każdy pakiet miał unikalny identyfikator UID na danym urządzeniu.

Ponieważ egzekwowanie zabezpieczeń odbywa się na poziomie procesu, kod 2 różnych pakietów nie może być zwykle uruchamiany w tym samym procesie, ponieważ muszą one działać jako różni użytkownicy Linuksa.

Wszystkie dane przechowywane przez aplikację są przypisane do identyfikatora użytkownika tej aplikacji i zwykle nie są dostępne dla innych pakietów.

Więcej informacji o modelu zabezpieczeń Androida znajdziesz w omówieniu zabezpieczeń Androida.

definiowanie i egzekwowanie uprawnień,

Aby wymusić własne uprawnienia, musisz najpierw zadeklarować je w pliku AndroidManifest.xml, używając co najmniej 1 elementu <permission>.

Konwencja nazewnictwa

System nie zezwala na deklarowanie uprawnień o tej samej nazwie przez wiele pakietów, chyba że wszystkie pakiety są podpisane tym samym certyfikatem. Jeśli pakiet deklaruje uprawnienie, system nie zezwala użytkownikowi na instalowanie innych pakietów o tej samej nazwie uprawnienia, chyba że są one podpisane tym samym certyfikatem co pierwszy pakiet.

Zalecamy dodanie do uprawnień prefiksu z nazwą pakietu aplikacji, używając nazwy w stylu domeny odwrotnej, po której następuje .permission., a następnie opis funkcji, którą reprezentuje uprawnienie, w formacie SNAKE_CASE. Na przykład: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Postępowanie zgodnie z tym zaleceniem pozwala uniknąć kolizji nazw i ułatwia jednoznaczną identyfikację właściciela oraz celu uprawnienia niestandardowego.

Przykład

Na przykład aplikacja, która musi kontrolować, które inne aplikacje mogą uruchamiać jedną z jej aktywności, może zadeklarować uprawnienia do tej operacji w ten sposób:

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

Atrybut protectionLevel jest wymagany i informuje system, jak powiadamiać użytkowników o aplikacjach wymagających uprawnień lub o tym, które aplikacje mogą mieć uprawnienia, zgodnie z opisem w powiązanej dokumentacji.

Atrybut android:permissionGroup jest opcjonalny i służy tylko do wyświetlania uprawnień użytkownikowi. W większości przypadków ustawia się standardową grupę systemową (wymienioną w android.Manifest.permission_group), ale możesz też zdefiniować własną grupę, jak opisano w następnej sekcji. Zalecamy użycie istniejącej grupy, ponieważ upraszcza to interfejs uprawnień wyświetlany użytkownikowi.

Musisz podać zarówno etykietę, jak i opis uprawnienia. Są to zasoby tekstowe, które użytkownik może zobaczyć, gdy wyświetla listę uprawnień (android:label) lub szczegóły pojedynczego uprawnienia (android:description). Etykieta jest krótka: zawiera kilka słów opisujących kluczową funkcję, którą chroni uprawnienie. Opis to kilka zdań wyjaśniających, co uprawnienie umożliwia posiadaczowi. Zgodnie z naszą konwencją opis składa się z 2 zdań, z których pierwsze opisuje uprawnienie, a drugie ostrzega użytkownika o tym, co może pójść nie tak, jeśli aplikacja otrzyma uprawnienie.

Oto przykład etykiety i opisu uprawnienia 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>

Tworzenie grupy uprawnień

Jak pokazano w poprzedniej sekcji, możesz użyć atrybutu android:permissionGroup, aby pomóc systemowi opisać uprawnienia użytkownikowi. W większości przypadków ustawia się standardową grupę systemową (wymienioną w android.Manifest.permission_group), ale możesz też zdefiniować własną grupę za pomocą <permission-group>.

Element <permission-group> definiuje etykietę dla zestawu uprawnień – zarówno tych zadeklarowanych w pliku manifestu za pomocą elementów <permission>, jak i tych zadeklarowanych w innym miejscu. Ma to wpływ tylko na sposób grupowania uprawnień, gdy są one prezentowane użytkownikowi. Element <permission-group> nie określa uprawnień należących do grupy, ale nadaje jej nazwę.

Możesz umieścić uprawnienie w grupie, przypisując nazwę grupy do atrybutu permissionGroup elementu <permission>.

Element <permission-tree> deklaruje przestrzeń nazw dla grupy uprawnień zdefiniowanych w kodzie.

Rekomendacje dotyczące uprawnień niestandardowych

Możesz zdefiniować niestandardowe uprawnienia dla swoich aplikacji i poprosić o niestandardowe uprawnienia z innych aplikacji, definiując elementy <uses-permission>. Zastanów się jednak, czy jest to konieczne.

  • Jeśli projektujesz pakiet aplikacji, które udostępniają sobie nawzajem funkcje, postaraj się, aby każde uprawnienie było zdefiniowane tylko raz. Musisz to zrobić, jeśli aplikacje nie są podpisane tym samym certyfikatem. Nawet jeśli wszystkie aplikacje są podpisane tym samym certyfikatem, sprawdzoną metodą jest definiowanie każdego uprawnienia tylko raz.
  • Jeśli funkcja jest dostępna tylko w aplikacjach podpisanych tym samym podpisem co aplikacja udostępniająca, możesz uniknąć definiowania uprawnień niestandardowych, używając sprawdzania podpisu. Gdy jedna z Twoich aplikacji wysyła żądanie do innej, druga aplikacja może sprawdzić, czy obie są podpisane tym samym certyfikatem, zanim spełni żądanie.

Jeśli uprawnienie niestandardowe jest konieczne, zastanów się, czy dostęp do niego powinny mieć tylko aplikacje podpisane przez tego samego dewelopera co aplikacja, która sprawdza uprawnienia – na przykład podczas wdrażania bezpiecznej komunikacji między procesami między 2 aplikacjami tego samego dewelopera. W takim przypadku zalecamy używanie uprawnień podpisu. Uprawnienia podpisu są przejrzyste dla użytkownika i pozwalają uniknąć uprawnień potwierdzanych przez użytkownika, które mogą być dla niego mylące.

Czytaj dalej:

<uses-permission>
Dokumentacja API dotycząca tagu manifestu, który deklaruje wymagane uprawnienia systemowe aplikacji.

Może Cię też zainteresować:

Android Security Overview
Szczegółowe omówienie modelu zabezpieczeń platformy Androida.