Definiowanie niestandardowych uprawnień aplikacji

Ten dokument opisuje, jak deweloperzy aplikacji mogą definiować własne uprawnienia za pomocą funkcji zabezpieczeń Androida. 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 przeglądzie.

Tło

Android to system operacyjny z osobnymi uprawnieniami, w którym każda aplikacja działa z inną tożsamością systemową (identyfikatorem użytkownika Linuksa i identyfikatorem grupy). Niektóre części systemu są też podzielone na różne tożsamości. W ten sposób Linux izoluje aplikacje od siebie nawzajem i od systemu.

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

Podpisywanie aplikacji

Wszystkie pliki APK muszą być podpisane certyfikatem, którego klucz prywatny posiada deweloper. Certyfikat nie musi być podpisany przez urząd certyfikacji. Używanie podpisanych samodzielnie certyfikatów jest dopuszczalne i typowe w przypadku aplikacji na Androida. Certyfikaty na Androidzie służą do rozróżniania autorów aplikacji. Dzięki temu system przyznaje lub odrzuca aplikacjom dostęp do uprawnień na poziomie podpisu oraz przyznaje lub odrzuca żądanie przyznania aplikacji tej samej tożsamości w systemie Linux co inna aplikacja.

Przyznaj uprawnienia do podpisywania po czasie wyprodukowania urządzenia

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

Możesz zadeklarować atrybut knownCerts i użyć flagi knownSigner w atrybucie protectionLevel aplikacji, aby uzyskać określone uprawnienie na poziomie podpisu. Następnie system przyznaje te uprawnienia aplikacji żądającej, jeśli dowolny podmiot podpisujący w historii podpisywania aplikacji żądającej, w tym obecny sygnatariusz, pasuje do jednego z skrótów zadeklarowanych z uprawnieniami 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 przypisuje każdemu pakietowi odrębnego identyfikatora użytkownika systemu Linux. Tożsamość jest taka sama przez cały okres ważności przesyłki na danym urządzeniu. Na różnych urządzeniach ten sam pakiet może mieć inny identyfikator UID. Istotne jest to, że każdy pakiet ma inny identyfikator UID na danym urządzeniu.

Egzekwowanie zabezpieczeń odbywa się na poziomie procesu, dlatego kod dwóch pakietów nie może działać w tym samym procesie, ponieważ muszą działać jako różni użytkownicy systemu Linux.

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

Więcej informacji o modelu zabezpieczeń Androida znajdziesz w artykule z omówieniem zabezpieczeń Androida.

Definiowanie i egzekwowanie uprawnień

Aby egzekwować własne uprawnienia, musisz najpierw zadeklarować je w AndroidManifest.xml przy użyciu co najmniej 1 elementu <permission>.

Konwencja nazewnictwa

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

Zalecamy poprzedzanie uprawnień nazwą pakietu aplikacji z użyciem odwrotnej nazwy typu domeny, po której następuje ciąg .permission., a potem opis funkcji, którą reprezentuje dane uprawnienie, w górnej części SNAKE_CASE. Przykład: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Zastosowanie się do tego zalecenia pozwala uniknąć kolizji w nazwach i pomaga wyraźnie określić właściciela i intencje niestandardowego uprawnienia.

Przykład

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

<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 informować użytkowników o aplikacjach wymagających tego uprawnienia oraz o tym, które aplikacje mogą je przyznawać zgodnie z opisem w linkowanej dokumentacji.

Atrybut android:permissionGroup jest opcjonalny i jest używany tylko do pomocy systemowi w wyświetlaniu uprawnień użytkownikowi. W większości przypadków jest to standardowa grupa systemowa (wymienione w android.Manifest.permission_group). Grupę możesz jednak zdefiniować samodzielnie, zgodnie z opisem w tej sekcji. Zalecamy użycie istniejącej grupy, ponieważ upraszcza to wyświetlany użytkownikowi interfejs uprawnień.

Musisz podać zarówno etykietę, jak i opis uprawnienia. Są to zasoby z ciągami tekstowymi, które użytkownik może zobaczyć podczas przeglądania 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ń opisujących, co umożliwia posiadaczowi uprawnienia. Zgodnie z tą konwencją pierwsze zdanie opisuje uprawnienia, a drugie ostrzega użytkownika przed rodzajem rzeczy, które mogą się nie powieść, gdy 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>

Utwórz grupę uprawnień

Jak pokazano w poprzedniej sekcji, możesz użyć atrybutu android:permissionGroup, aby ułatwić systemowi opisanie uprawnień użytkownikowi. W większości przypadków jest to standardowa grupa systemowa (wymienione w android.Manifest.permission_group), ale możesz też zdefiniować własną grupę za pomocą <permission-group>.

Element <permission-group> określa etykietę zbioru uprawnień – zarówno tych zadeklarowanych w pliku manifestu z elementami <permission>, jak i tych zadeklarowanych w innym miejscu. Ma to wpływ tylko na sposób grupowania uprawnień prezentowanych użytkownikowi. Element <permission-group> nie określa uprawnień należących do grupy, ale nadaje grupie nazwę.

Uprawnienia możesz umieścić w grupie, przypisując jej nazwę do atrybutu permissionGroup elementu <permission>.

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

Rekomendacje dotyczące niestandardowych uprawnień

Możesz definiować uprawnienia niestandardowe dla swoich aplikacji i prosić o uprawnienia innych aplikacji, definiując elementy <uses-permission>. Uważnie się zastanów, czy jest to konieczne.

  • Jeśli projektujesz pakiet aplikacji, które udostępniają sobie nawzajem funkcje, spróbuj je zaprojektować w taki sposób, aby każde uprawnienie było zdefiniowane tylko raz. Musisz to zrobić, jeśli nie wszystkie aplikacje są podpisane tym samym certyfikatem. Nawet jeśli wszystkie aplikacje są podpisane tym samym certyfikatem, najlepiej jest zdefiniować każde uprawnienie tylko raz.
  • Jeśli ta funkcja jest dostępna tylko w przypadku aplikacji podpisanych tym samym podpisem co aplikacja udostępniająca, możesz uniknąć definiowania uprawnień niestandardowych przez sprawdzanie podpisu. Gdy jedna z Twoich aplikacji wysyła żądanie do innej, ta druga może sprawdzić, czy obie są podpisane tym samym certyfikatem, zanim spełnią to żądanie.

Jeśli potrzebujesz uprawnień niestandardowych, zastanów się, czy dostęp do nich mają tylko aplikacje podpisane przez tego samego dewelopera co aplikacja, która sprawdza uprawnienia, np. w przypadku implementowania bezpiecznej komunikacji między procesami między 2 aplikacjami tego samego dewelopera. Jeśli tak, zalecamy użycie uprawnień do podpisu. Uprawnienia do podpisu są przejrzyste dla użytkownika i unikają uprawnień potwierdzonych przez użytkownika, co może być mylące dla użytkowników.

Przeczytaj więcej na te tematy:

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

Może Cię też zainteresować:

Omówienie bezpieczeństwa Androida
Szczegółowa dyskusja na temat modelu zabezpieczeń platformy Android.