Definiowanie niestandardowych uprawnień aplikacji

Z tego dokumentu dowiesz się, jak deweloperzy aplikacji mogą korzystać z funkcji zabezpieczeń udostępnianych przez Androida, aby definiować własne uprawnienia. Dzięki zdefiniowaniu uprawnień niestandardowych aplikacja może udostępniać swoje zasoby i funkcje innym aplikacjom. Więcej informacji o uprawnieniach znajdziesz w omówieniu uprawnień.

Tło

Android to system operacyjny z wydzielonymi uprawnieniami, w którym każda aplikacja działa z odrębną tożsamością systemową (identyfikatorem użytkownika i identyfikatorem grupy w systemie Linux). Części systemu są też rozdzielone na odrębne tożsamości. Dzięki temu Linux izoluje aplikacje od siebie i od systemu.

Aplikacje mogą udostępniać swoje funkcje innym aplikacjom, definiując uprawnienia, o które inne aplikacje mogą prosić. Mogą też określać 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ą korzystać z certyfikatów podpisanych samodzielnie. Jest to dopuszczalne i typowe. Certyfikaty w Androidzie służą do odróżniania autorów aplikacji. Dzięki temu system może przyznawać lub odmawiać aplikacjom dostępu do uprawnień na poziomie podpisu oraz przyznawać lub odmawiać prośby aplikacji o przyznanie jej tej samej tożsamości Linuxa co inna aplikacja.

Przyznawanie uprawnień do podpisywania po upływie czasu produkcji urządzenia

Począwszy od Androida 12 (interfejs API na poziomie 31), atrybut knownCerts w przypadku 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 w pliku 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 z podpisujących w jej łańcuchu podpisywania, w tym bieżący podpisujący, pasuje do jednego z skrótów zadeklarowanych w atrybucie knownCerts.

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

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

Podczas instalacji Android przypisuje każdemu pakietowi odrębny identyfikator użytkownika w systemie Linux. Identyfikator pozostaje stały przez cały okres użytkowania 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ł na danym urządzeniu niepowtarzalny identyfikator UID.

Ponieważ egzekwowanie zabezpieczeń odbywa się na poziomie procesu, kod dwóch pakietów nie może zwykle działać w tym samym procesie, ponieważ musi być uruchamiany jako różni użytkownicy systemu Linux.

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

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

Określanie i egzekwowanie uprawnień

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

Konwencja nazewnictwa

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

Zalecamy dodawanie do uprawnień prefiksu w postaci nazwy pakietu aplikacji w formacie nazwy domeny odwróconej, po którym następuje znak .permission., a potem opis funkcji, którą reprezentuje uprawnienie, zapisany wielkimi literami w formacie SNAKE_CASE. Na przykład:com.example.myapp.permission.ENGAGE_HYPERSPACE.

Postępowanie zgodnie z tą rekomendacją pozwala uniknąć kolizji nazw i ułatwia jasne określenie właściciela i przeznaczenia 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ć uprawnienie 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 które aplikacje mogą mieć uprawnienia, zgodnie z opisem w dokumentacji, do której prowadzi link.

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ę zgodnie z opisem 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ć podczas wyświetlania listy uprawnień (android:label) lub szczegółów pojedynczego uprawnienia (android:description). Etykieta jest krótka: kilka słów opisujących kluczową funkcję, którą chroni uprawnienie. Opis to kilka zdań wyjaśniających, co umożliwia posiadaczowi uprawnienie. Zgodnie z naszą konwencją opis składa się z 2 zdań. Pierwsze zdanie opisuje uprawnienie, a drugie ostrzega użytkownika przed tym, co może się stać, jeśli aplikacja otrzyma to 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 w opisywaniu uprawnień użytkownikowi. W większości przypadków ustawia się standardową grupę systemową (wymienioną w android.Manifest.permission_group), ale można 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 innych miejscach. Ma to wpływ tylko na sposób grupowania uprawnień wyświetlanych 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 elementu<permission>permissionGroup.

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

Spersonalizowane rekomendacje dotyczące uprawnień

Możesz zdefiniować niestandardowe uprawnienia dla swoich aplikacji i żądać niestandardowych uprawnień od 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, staraj 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 zdefiniowanie każdego uprawnienia tylko raz.
  • Jeśli funkcja jest dostępna tylko dla aplikacji podpisanych tym samym podpisem co aplikacja udostępniająca, możesz uniknąć definiowania uprawnień niestandardowych, korzystając ze sprawdzania podpisu. Gdy jedna z Twoich aplikacji wysyła żądanie do innej, ta druga może przed jego wykonaniem sprawdzić, czy obie aplikacje są podpisane tym samym certyfikatem.

Jeśli wymagane jest uprawnienie niestandardowe, zastanów się, czy dostęp do niego powinny mieć tylko aplikacje podpisane przez tego samego dewelopera co aplikacja sprawdzająca uprawnienia. Może to być przydatne np. w przypadku implementowania bezpiecznej komunikacji międzyprocesowej między 2 aplikacjami tego samego dewelopera. W takim przypadku zalecamy korzystanie z uprawnień do podpisu. Uprawnienia do podpisu są przejrzyste dla użytkownika i nie wymagają potwierdzenia przez niego, co może być dla niego mylące.

Więcej informacji:

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

Może Cię również zainteresować:

Omówienie bezpieczeństwa Androida
Szczegółowe omówienie modelu bezpieczeństwa platformy Android.