Android 權(quán)限控制機(jī)制

1.應(yīng)用權(quán)限機(jī)制

2.Android版本權(quán)限變更

3.應(yīng)用權(quán)限變更適配實(shí)例

4.默認(rèn)授權(quán)

5.AppOps機(jī)制

6.Selinux權(quán)限介紹

1.應(yīng)用權(quán)限機(jī)制

權(quán)限機(jī)制陌知?

Android 是一個(gè)權(quán)限分離的系統(tǒng)。這是利用 Linux 已有的權(quán)限管理機(jī)制礼仗,通過(guò)為每一個(gè) Application 分配不同的 uid 和 gid,從而使得不同的 Application 之間的私有數(shù)據(jù)和訪問(wèn)(native 以及 Java 層通過(guò)這種機(jī)制,都可以)達(dá)到隔離的目的元践。與此同時(shí)韭脊,Android 還在此基礎(chǔ)上進(jìn)行擴(kuò)展,提供了permission機(jī)制单旁,它主要是用來(lái)對(duì) Application 可以執(zhí)行的某些具體操作進(jìn)行權(quán)限細(xì)分和訪問(wèn)控制沪羔,同時(shí)提供了URI permission機(jī)制,用來(lái)提供對(duì)某些特定的數(shù)據(jù)塊進(jìn)行專(zhuān)門(mén)權(quán)限進(jìn)行限制象浑。

Android Permission權(quán)限機(jī)制是對(duì)Android安全機(jī)制的一個(gè)重要補(bǔ)充蔫饰,控制了應(yīng)用對(duì)于系統(tǒng)接口或者對(duì)外接口的訪問(wèn)。

權(quán)限信息:

權(quán)限信息

可以使用adb shell pm list permissions -f 命令詳細(xì)查看 Android 預(yù)定義的權(quán)限詳細(xì)信息(危險(xiǎn)權(quán)限組未在此列表中), 例如下所示:

系統(tǒng)目錄下查看聲明的權(quán)限信息路徑:

frameworks/base/core/res/AndroidManifest.xml

常用權(quán)限命令:

pm list permission-groups

打印所有已知的權(quán)限組

pm list permissions [options] [GROUP]

打印權(quán)限

例如:pm list permissions –g -d (危險(xiǎn)權(quán)限組信息)

危險(xiǎn)權(quán)限信息

其它常用參數(shù):

其它命令

權(quán)限級(jí)別:

描述權(quán)限中隱含的潛在風(fēng)險(xiǎn)愉豺,并指示系統(tǒng)在確定是否將權(quán)限授予請(qǐng)求它的應(yīng)用程序時(shí)應(yīng)遵循的程序死嗦。Standard permissions具有預(yù)定義的永久保護(hù)級(jí)別。如果您在應(yīng)用程序中創(chuàng)建自定義權(quán)限粒氧,您可以使用下面列出的值之一定義 protectionLevel 屬性。如果沒(méi)有為自定義權(quán)限定義 protectionLevel节腐,則系統(tǒng)分配默認(rèn)值(“normal”)外盯。

每個(gè)保護(hù)級(jí)別由基本權(quán)限類(lèi)型和零個(gè)或多個(gè)標(biāo)志組成(5個(gè)基本類(lèi)型, 22個(gè)附加類(lèi)型)。

使用以下函數(shù)來(lái)提取它們:

int basePermissionType = permissionInfo.getProtection(); --- 基本權(quán)限類(lèi)型

int permissionFlags = permissionInfo.getProtectionFlags(); --- 附加權(quán)限標(biāo)志

基本權(quán)限類(lèi)型:

基本權(quán)限類(lèi)型

其它附加權(quán)限標(biāo)志,見(jiàn)如下google官網(wǎng)說(shuō)明:

https://developer.android.com/reference/android/R.attr?hl=zh-cn#protectionLevel

權(quán)限管理:

應(yīng)用安裝時(shí)翼雀,就給權(quán)限賦予了對(duì)應(yīng)的狀態(tài)饱苟,系統(tǒng)是使用PMS來(lái)管理權(quán)限。PMS維護(hù)管理權(quán)限狀態(tài)數(shù)據(jù)狼渊,Android6.0之前箱熬,保存在data/system/packages.xml中;6.0之后增加了data/*../runtime-permissions.xml,數(shù)據(jù)持久化存儲(chǔ)文件狈邑,用于記錄著運(yùn)行時(shí)權(quán)限的授予和拒絕狀態(tài)城须,當(dāng)權(quán)限狀態(tài)變更時(shí),申請(qǐng)的結(jié)果會(huì)動(dòng)態(tài)更新 granted 值和flags狀態(tài)米苹。

權(quán)限狀態(tài)

權(quán)限查看:

Android12的runtime-permissions.xml被默認(rèn)設(shè)置二進(jìn)制xml格式糕伐,直接打開(kāi)是亂碼。

通過(guò)修改配置將其改為普通的xml格式: adb shell setprop persist.sys.binary_xml false

重啟手機(jī)蘸嘶,再獲取runtime-permissions.xml良瞧,就是普通xml格式。

權(quán)限授予

動(dòng)態(tài)授權(quán):

Android6.0 此版本引入了一種新的權(quán)限模式训唱,用戶可直接在運(yùn)行時(shí)管理應(yīng)用權(quán)限褥蚯。這種模式讓用戶能夠更好地了解和控制權(quán)限,同時(shí)為應(yīng)用開(kāi)發(fā)者精簡(jiǎn)了安裝和自動(dòng)更新過(guò)程况增。用戶可為所安裝的各個(gè)應(yīng)用分別授予或撤銷(xiāo)權(quán)限赞庶。

權(quán)限申請(qǐng):

運(yùn)行時(shí)權(quán)限授權(quán)流程

權(quán)限檢查:

檢查用戶是否已向您的應(yīng)用授予特定權(quán)限,將該權(quán)限傳入checkSelfPermission() 方法。根據(jù)您的應(yīng)用是否具有相應(yīng)權(quán)限尘执,此方法會(huì)返回PackageManager.PERMISSION_GRANTED(0)

或PackageManager.PERMISSION_DENIED(-1)舍哄。

檢查權(quán)限方法

檢查應(yīng)用自身權(quán)限,建議使用checkSelfPermission誊锭;

檢查IPC的調(diào)用進(jìn)程權(quán)限表悬,建議使用checkCallingPermission(或者checkCallingOrSelfPermission);

指定PID、UID檢查權(quán)限丧靡,建議使用checkPermission蟆沫;

訪問(wèn)其它應(yīng)用數(shù)據(jù)庫(kù),建議先檢查訪問(wèn)的URI是否有權(quán)限温治;

底層進(jìn)行權(quán)限檢查:

我們了解了運(yùn)行時(shí)權(quán)限在系統(tǒng)API接口調(diào)用的時(shí)候會(huì)去檢查權(quán)限狀態(tài)饭庞,但有些權(quán)限例如INTERNET、READ_LOGS熬荆、BLUETOOTH等調(diào)用框架層接口的時(shí)候并沒(méi)有去檢查權(quán)限舟山,這類(lèi)權(quán)限是如何檢查授權(quán)的呢?

在底層卤恳,Linux內(nèi)核使用用戶和用戶組來(lái)實(shí)施權(quán)限控制累盗,這套權(quán)限模型是從Linux繼承過(guò)來(lái)的,用于對(duì)文件系統(tǒng)實(shí)體進(jìn)行訪問(wèn)控制突琳,也可以對(duì)其他Android特定資源進(jìn)行控制若债。這一模型通常被稱為Android沙箱。以DalvikVM和Android框架形式存在的Android運(yùn)行時(shí)實(shí)施了第二套權(quán)限模型拆融。這套模型在用戶安裝應(yīng)用時(shí)是向用戶公開(kāi)的蠢琳,定義了應(yīng)用擁有的權(quán)限,從而限制Android應(yīng)用的能力镜豹。事實(shí)上傲须,第二套權(quán)限模型中的某些權(quán)限直接映射到底層操作系統(tǒng)上的特定用戶、用戶組和權(quán)能趟脂。

內(nèi)核和系統(tǒng)守護(hù)進(jìn)程通過(guò)進(jìn)程分配的 GID躏碳、UID和補(bǔ)充 GID來(lái)決定是否要賦予進(jìn)程權(quán)限。

Android的權(quán)限模型是多方面的散怖,有API權(quán)限菇绵、文件系統(tǒng)權(quán)限和IPC權(quán)限。在很多情況下镇眷,這些權(quán)限都會(huì)交織在一起咬最。一些高級(jí)權(quán)限會(huì)后退映射到低級(jí)別的操作系統(tǒng)權(quán)能,這可能包括打開(kāi)套接字欠动、藍(lán)牙設(shè)備和文件系統(tǒng)路徑等永乌。

應(yīng)用在AndroidMainfest.xml申明的權(quán)限如何映射到底層的UID惑申、GID?

內(nèi)置權(quán)限到GID的映射定義在/etc/permissions/platform.xml 中

包管理器在啟動(dòng)時(shí)讀取 platform.xml翅雏,并維護(hù)「permission-GID」對(duì)應(yīng)的列表圈驼。當(dāng)它給安裝中的包授權(quán)時(shí),會(huì)把權(quán)限對(duì)應(yīng)的 GID 加入到該應(yīng)用進(jìn)程的補(bǔ)充 GID 中望几。

權(quán)限對(duì)應(yīng)的 GID 加入到該應(yīng)用進(jìn)程的補(bǔ)充 GID 中绩脆,可以通過(guò)adb shell--cd proc--cd PID--cat status查看:

system/core/libcutils/include/private/android_filesystem_config.h

static const struct android_id_info android_ids[] = {

{ "camera", AID_CAMERA, },

{ "sdcard_r", AID_SDCARD_R, },

{ "sdcard_rw", AID_SDCARD_RW, },

{ "inet", AID_INET},
 ···
};

:AndroidN及之前android_ids放在android_filesystem_config.h中之后版本遷移到pwd/grp functionality.

Android定義了從名稱到獨(dú)特標(biāo)識(shí)符Android ID(AID)的映射表。初始的AID映射表包含了一些與特權(quán)用戶及系統(tǒng)關(guān)鍵用戶(如system用戶/用戶組)對(duì)應(yīng)的靜態(tài)保留條目橄抹。Android還保留了一段AID范圍靴迫,用于提供原生應(yīng)用的UID。Android 4.1之后的版本為多用戶資料檔案和隔離進(jìn)程用戶增加了額外的AID范圍段(如Chrome沙箱)楼誓。

除了AID玉锌,Android還使用了輔助用戶組機(jī)制,以允許進(jìn)程訪問(wèn)共享或受保護(hù)的資源疟羹。例如主守,sdcard_rw用戶組中的成員允許進(jìn)程讀寫(xiě)/sdcard目錄,因?yàn)樗募虞d項(xiàng)規(guī)定了哪些用戶組可以讀寫(xiě)該目錄榄融。這與許多Linux發(fā)行版中對(duì)輔助用戶組機(jī)制的使用是類(lèi)似的丸逸。

注意 盡管所有的AID條目都映射到一個(gè)UID和GID,但是UID在描述系統(tǒng)上的一個(gè)用戶時(shí)并不是必需的剃袍。例如,AID_SDCARD_RW映射到sdcard_rw捎谨,但是它僅僅用作一個(gè)輔助用戶組民效,而不是系統(tǒng)上的UID。

在應(yīng)用執(zhí)行時(shí)涛救,它們的UID畏邢、GID和輔助用戶組都會(huì)被分配給新創(chuàng)建的進(jìn)程。在一個(gè)獨(dú)特UID和GID環(huán)境下運(yùn)行检吆,使得操作系統(tǒng)可以在內(nèi)核中實(shí)施底層的限制措施舒萎,也讓運(yùn)行環(huán)境能夠控制應(yīng)用之間的交互。這就是Android沙箱的關(guān)鍵所在蹭沛。

在應(yīng)用包條目中定義的權(quán)限后面會(huì)通過(guò)兩種方式實(shí)施檢查:一種檢查在調(diào)用給定方法時(shí)進(jìn)行臂寝,由運(yùn)行環(huán)境實(shí)施;另一種檢查在操作系統(tǒng)底層進(jìn)行摊灭,由庫(kù)或內(nèi)核實(shí)施咆贬。

權(quán)限對(duì)應(yīng)的 GID 何時(shí)被加入到應(yīng)用進(jìn)程的補(bǔ)充 GID 中?

每個(gè)應(yīng)用都會(huì)運(yùn)行在自己的 Dalvik 虛擬機(jī)進(jìn)程中帚呼,但是為了提高啟動(dòng)效率掏缎,Android 不會(huì)為每個(gè)應(yīng)用都新建一個(gè) Dalvik 進(jìn)程皱蹦,而是采用 fork 的形式。每個(gè)進(jìn)程都 fork form zygote 進(jìn)程眷蜈。

因?yàn)?zygote 進(jìn)程已經(jīng)預(yù)加載了大部分核心和 Java 應(yīng)用框架庫(kù)沪哺,fork 的子進(jìn)程會(huì)繼承 zygote 的進(jìn)程空間,也就是說(shuō)酌儒,fork 的子進(jìn)程辜妓,可以共享這些預(yù)加載的副本(記住,是副本今豆,不是直接共享嫌拣。fork 時(shí),會(huì) copy-on-write 預(yù)加載的內(nèi)容)呆躲,減少了重新加載核心庫(kù)的時(shí)間异逐。

當(dāng) zygote 收到啟動(dòng)新進(jìn)程的請(qǐng)求時(shí),它會(huì) fork 自身出一個(gè)子進(jìn)程插掂,并對(duì)該子進(jìn)程做特殊化處理灰瞻。其源代碼位于 framework/base/core/jni/com_android_internal_os_Zygote.cpp 中。SpecializeCommon() 的主要代碼如下:

這里設(shè)置進(jìn)程的組 ID 和用戶 ID辅甥,通過(guò) fork 創(chuàng)建的子進(jìn)程調(diào)用 setgroups Intarray 設(shè)置該進(jìn)程所屬的組酝润,這樣應(yīng)用程序就擁有了該組的權(quán)限,并且可以通過(guò) setgid() 及 setuid() 確定應(yīng)用程序的 GID 及 UID 值璃弄。

每個(gè)應(yīng)用進(jìn)程都分配好自己的 GID要销、UID和補(bǔ)充 GID,系統(tǒng)內(nèi)核和守護(hù)進(jìn)程就可以用這些標(biāo)識(shí)來(lái)決定夏块,是否要賦予進(jìn)程權(quán)限疏咐。

應(yīng)用權(quán)限內(nèi)容:

應(yīng)用權(quán)限

2.Android版本權(quán)限變更

Android從1.0開(kāi)始其根基Linux繼承了已經(jīng)深入人心的類(lèi)Unix進(jìn)程隔離機(jī)制與最小權(quán)限原則。引入了Android沙箱及擴(kuò)展了Android使用的權(quán)限模型脐供,包括Android對(duì)Unix系統(tǒng)UID/GID映射關(guān)系的特殊實(shí)現(xiàn)AID浑塞,以及在整個(gè)系統(tǒng)中實(shí)施的限制和權(quán)能。

目前到Android13.0各版本中有關(guān)權(quán)限變更的重要調(diào)整如下:

版本 重要變更
1.6 新增WRITE_EXTERNAL_STORAGE權(quán)限政己,允許程序?qū)懭胪獠看鎯?chǔ)
2.2 android.permission.KILL_BACKGROUND_PROCESSES— 允許應(yīng)用程序調(diào)用killBackgroundProcesses(String)
2.3
image.png
3.0
image.png
4.0
image.png
4.0.3
image.png
4.1
image.png
4.2 精細(xì)化區(qū)分ACCESS_COARSE_LOCATION權(quán)限和ACCESS_FINE_LOCATION,不請(qǐng)求FINE_LOCATION獲取的位置結(jié)果可能不太準(zhǔn)確
4.3 BIND_NOTIFICATION_LISTENER_SERVICE:需要使用新的 NotificationListenerService API
4.4 從 Android 4.4 開(kāi)始酌壕,當(dāng)您僅訪問(wèn)您的應(yīng)用特定外部存儲(chǔ)區(qū)域時(shí),此平臺(tái)不再要求您的應(yīng)用獲取 WRITE_EXTERNAL_STORAGE 或 READ_EXTERNAL_STORAGE歇由。不過(guò)卵牍,如果您要訪問(wèn) getExternalStoragePublicDirectory() 提供的外部存儲(chǔ)空間的可共享區(qū)域,則需要這些權(quán)限
5.0
image.png
6.0 此版本引入了一種新的權(quán)限模式沦泌,如今辽慕,用戶可直接在運(yùn)行時(shí)管理應(yīng)用權(quán)限。這種模式讓用戶能夠更好地了解和控制權(quán)限赦肃,同時(shí)為應(yīng)用開(kāi)發(fā)者精簡(jiǎn)了安裝和自動(dòng)更新過(guò)程溅蛉。用戶可為所安裝的各個(gè)應(yīng)用分別授予或撤銷(xiāo)權(quán)限公浪。對(duì)于以 Android 6.0(API 級(jí)別 23)或更高版本為目標(biāo)平臺(tái)的應(yīng)用,請(qǐng)務(wù)必在運(yùn)行時(shí)檢查和請(qǐng)求權(quán)限船侧。要確定您的應(yīng)用是否已被授予權(quán)限欠气,請(qǐng)調(diào)用新增的 checkSelfPermission() 方法。要請(qǐng)求權(quán)限镜撩,請(qǐng)調(diào)用新增的 requestPermissions() 方法预柒。即使您的應(yīng)用并不以 Android 6.0(API 級(jí)別 23)為目標(biāo)平臺(tái),您也應(yīng)該在新權(quán)限模式下測(cè)試您的應(yīng)用袁梗。
7.0 文件系統(tǒng)權(quán)限更改:為了提高隱私文件的安全性宜鸯,Android 7.0 或更高版本的應(yīng)用程序的隱私目錄已限制訪問(wèn)。
8.0 在 Android 8.0 之前遮怜,如果應(yīng)用在運(yùn)行時(shí)請(qǐng)求權(quán)限并且被授予該權(quán)限淋袖,系統(tǒng)會(huì)錯(cuò)誤地將屬于同一權(quán)限組并且在清單中注冊(cè)的其他權(quán)限也一起授予應(yīng)用。對(duì)于針對(duì) Android 8.0 的應(yīng)用锯梁,此行為已被糾正即碗。系統(tǒng)只會(huì)授予應(yīng)用明確請(qǐng)求的權(quán)限。然而陌凳,一旦用戶為應(yīng)用授予某個(gè)權(quán)限剥懒,則所有后續(xù)對(duì)該權(quán)限組中權(quán)限的請(qǐng)求都將被自動(dòng)批準(zhǔn)。
9.0 為了增強(qiáng)用戶隱私合敦,Android 9 引入了若干行為變更初橘,如限制后臺(tái)應(yīng)用訪問(wèn)設(shè)備傳感器、限制通過(guò) Wi-Fi 掃描檢索到的信息充岛,以及與通話保檐、手機(jī)狀態(tài)和 Wi-Fi 掃描相關(guān)的新權(quán)限規(guī)則和權(quán)限組。無(wú)論采用哪一種目標(biāo) SDK 版本裸准,這些變更都會(huì)影響運(yùn)行于 Android 9 上的所有應(yīng)用。
10
image.png
11 Android 11 對(duì)應(yīng)用授予權(quán)限的方式進(jìn)行了多項(xiàng)更改赔硫。這些更改旨在通過(guò)更加有意地授予權(quán)限來(lái)保護(hù)用戶炒俱。強(qiáng)制執(zhí)行分區(qū)存儲(chǔ)、單次授權(quán)爪膊、自動(dòng)重置權(quán)限权悟、后臺(tái)位置信息訪問(wèn)權(quán)限、軟件包可見(jiàn)性推盛、前臺(tái)服務(wù)等的調(diào)整峦阁。
12 在搭載 Android 12 或更高版本的設(shè)備上,用戶可以要求您的應(yīng)用只能訪問(wèn)大致位置信息耘成。
13 存儲(chǔ)權(quán)限變更榔昔、新增通知權(quán)限驹闰、后臺(tái)使用身體傳感器權(quán)限。

總結(jié):從Android版本迭代有關(guān)權(quán)限變更來(lái)看撒会,Android6.0之前基本是針對(duì)權(quán)限進(jìn)行擴(kuò)展調(diào)整嘹朗,Android6.0之后加強(qiáng)了用戶對(duì)系統(tǒng)的安全管控,Android10.0之后權(quán)限管控更加嚴(yán)格诵肛,進(jìn)一步提升用戶安全性屹培。

Google各版本變更信息:https://developer.android.com/about/versions

3.應(yīng)用權(quán)限變更適配實(shí)例

實(shí)例一:后臺(tái)定位權(quán)限適配

為了讓用戶更好地控制應(yīng)用對(duì)位置信息的訪問(wèn)權(quán)限,Android 10 引入了 ACCESS_BACKGROUND_LOCATION 權(quán)限怔檩。與 ACCESS_FINE_LOCATION 和 ACCESS_COARSE_LOCATION 權(quán)限不同褪秀,ACCESS_BACKGROUND_LOCATION 權(quán)限僅會(huì)影響應(yīng)用在后臺(tái)運(yùn)行時(shí)對(duì)位置信息的訪問(wèn)權(quán)限。除非符合以下條件之一薛训,否則應(yīng)用將被視為在后臺(tái)訪問(wèn)位置信息:

.屬于該應(yīng)用的 Activity 可見(jiàn)媒吗。

.該應(yīng)用運(yùn)行的某個(gè)前臺(tái)設(shè)備已聲明前臺(tái)服務(wù)類(lèi)型為 location。

.要聲明您的應(yīng)用中的某個(gè)服務(wù)的前臺(tái)服務(wù)類(lèi)型许蓖,請(qǐng)將應(yīng)用的 targetSdkVersion 或 compileSdkVersion 設(shè)置為 29 或更高版本蝴猪。

定位權(quán)限狀態(tài)

AndroidQ(10) 獲取后臺(tái)定位權(quán)限:

1.Android 10 之前只有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION;

2.Android 10 新增加了后臺(tái)定位權(quán)限:ACCESS_BACKGROUND_LOCATION膊爪,該權(quán)限對(duì)應(yīng)始終允許自阱;老的權(quán)限: ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION代表僅前臺(tái)使用允許;

3.應(yīng)用的targetSdkVersion<Q米酬,谷歌提供了兼容性方案沛豌,只要應(yīng)用申請(qǐng)了老的位置權(quán)限ACCESS_FINE_LOCATION或者ACCESS_COARSE_LOCATION,會(huì)默認(rèn)請(qǐng)求ACCESS_BACKGROUND_LOCATION權(quán)限赃额,動(dòng)態(tài)彈框根據(jù)用戶選擇授權(quán)加派。

4.應(yīng)用的targetSdkVersion>=Q,如果應(yīng)用必須要始終定位跳芳,可以只申請(qǐng)ACCESS_BACKGROUND_LOCATION即可芍锦;如果應(yīng)用只需要申請(qǐng)前臺(tái)定位,則只需要申請(qǐng)老的定位權(quán)限即可飞盆。

5.如果用戶選擇僅前臺(tái)使用允許娄琉,應(yīng)用的頁(yè)面退后臺(tái),通過(guò)啟動(dòng)前臺(tái)服務(wù)讓?xiě)?yīng)用處于前臺(tái)狀態(tài)吓歇,必須把前臺(tái)服務(wù)標(biāo)為:foregroundServiceType=“l(fā)ocation”孽水,才能獲取位置信息。

<manifest> ...

<service  android:name="com.amap.api.location.APSService"

android:foregroundServiceType="location" />

 </manifest>
定位權(quán)限授權(quán)對(duì)比

Android R(11) 獲取后臺(tái)位置權(quán)限:

當(dāng)應(yīng)用申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限時(shí),讓用戶授予權(quán)限的彈窗中,將不再提供“始終允許”的選項(xiàng)堡赔,這個(gè)選項(xiàng)只存在于設(shè)置中的應(yīng)用權(quán)限授予頁(yè)面魁袜,并且后臺(tái)位置權(quán)限的申請(qǐng)需要應(yīng)用已經(jīng)擁有前臺(tái)位置權(quán)限析恢。

適配建議:

若您的應(yīng)用確定需要獲得后臺(tái)位置信息訪問(wèn)的權(quán)限咙轩,現(xiàn)在則需要分為兩個(gè)步驟眶明,因?yàn)橐褵o(wú)法在沒(méi)有前臺(tái)位置信息訪問(wèn)權(quán)限的時(shí)候直接申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限惩坑。

  1. 先申請(qǐng)前臺(tái)位置信息訪問(wèn)權(quán)限簇搅;

  2. 再申請(qǐng)后臺(tái)位置信息訪問(wèn)權(quán)限完域,引導(dǎo)用戶到設(shè)置中進(jìn)行授予。

Android S(12) 獲取后臺(tái)位置權(quán)限:

在搭載 Android 12 或更高版本的設(shè)備上瘩将,用戶可以要求您的應(yīng)用只能訪問(wèn)大致位置信息吟税。

確切位置:可訪問(wèn)確切位置信息(10英尺到160英尺)。

大致位置:只能訪問(wèn)大致位置信息(1 英里)姿现。

注意:如果用戶從權(quán)限對(duì)話框或在系統(tǒng)設(shè)置中將應(yīng)用的位置信息使用權(quán)從確切位置降級(jí)到大致位置肠仪,系統(tǒng)會(huì)重啟應(yīng)用的進(jìn)程。

實(shí)例二:存儲(chǔ)權(quán)限適配

為了讓用戶更好地控制自己的文件并減少混亂备典,Android 10 針對(duì)應(yīng)用推出了一種新的存儲(chǔ)范例异旧,稱為分區(qū)存儲(chǔ)。分區(qū)存儲(chǔ)改變了應(yīng)用在設(shè)備的外部存儲(chǔ)設(shè)備中存儲(chǔ)和訪問(wèn)文件的方式提佣。

受影響的文件接口

AndroidQ(10) 獲取外部存儲(chǔ):

1.應(yīng)用targetSdkVersion<Q(29) 按照請(qǐng)求應(yīng)用權(quán)限中所述的最佳做法吮蛹,請(qǐng)求 READ\WRITE_EXTERNAL_STORAGE 權(quán)限。

或者使用 MediaStore API 修改或刪除媒體文件拌屏。

2.如果您的應(yīng)用以 Android 10(API 級(jí)別 29)為目標(biāo)平臺(tái)targetSdkVersion=Q(29)潮针,請(qǐng)停用分區(qū)存儲(chǔ),繼續(xù)使用適用于 Android 9 及更低版本的方法來(lái)執(zhí)行此操作。

如果您以 Android 10 為目標(biāo)平臺(tái)倚喂,則需要在應(yīng)用的清單文件中將 requestLegacyExternalStorage 的值設(shè)置為 true:

<manifest ... >

 <!-- This attribute is "false" by default on apps targeting

 Android 10\. -->

 <application android:requestLegacyExternalStorage="true" ... >
 ...
 </application>

</manifest>

AndroidR(11) 及更高版本獲取外部存儲(chǔ):

1.使用 MediaStore.createWriteRequest() 或 MediaStore.createTrashRequest() 為應(yīng)用的寫(xiě)入或刪除請(qǐng)求創(chuàng)建待定 intent每篷,然后通過(guò)調(diào)用該 intent 提示用戶授予修改一組文件的權(quán)限。

注意:在 Android 11 或更高版本(無(wú)論目標(biāo) SDK 級(jí)別是什么)中端圈,其他應(yīng)用無(wú)法訪問(wèn)外部存儲(chǔ)設(shè)備上的應(yīng)用專(zhuān)用目錄中存儲(chǔ)的文件焦读。

Android 存儲(chǔ)用例和最佳做法 :

https://developer.android.com/training/data-storage/use-cases

實(shí)例三:獲取應(yīng)用列表

Android 11 更改了應(yīng)用查詢用戶已在設(shè)備上安裝的其他應(yīng)用以及與之交互的方式。使用 <queries> 元素舱权,應(yīng)用可以定義一組自身可訪問(wèn)的其他軟件包矗晃。通過(guò)告知系統(tǒng)應(yīng)向您的應(yīng)用顯示哪些其他軟件包,此元素有助于鼓勵(lì)最小權(quán)限原則宴倍。

受影響的接口:

 .PackageManager.getInstalledApplications

 .PackageManager.getInstalledPackages

只返回系統(tǒng)可見(jiàn)以及與應(yīng)用交互授權(quán)的應(yīng)用列表张症。

以 Android 11(API 級(jí)別 30)或更高版本為目標(biāo)平臺(tái),部分類(lèi)型的應(yīng)用也始終對(duì)您的應(yīng)用可見(jiàn):詳見(jiàn)以下文檔

https://developer.android.com/training/basics/intents/package-visibility?hl=zh-cn#automatic

查詢所有應(yīng)用及與之交互:

在極少數(shù)情況下啊楚,您的應(yīng)用可能需要查詢?cè)O(shè)備上的所有已安裝應(yīng)用或與之交互吠冤,不管這些應(yīng)用包含哪些組件浑彰。為了允許您的應(yīng)用看到其他所有已安裝應(yīng)用恭理,系統(tǒng)會(huì)提供 QUERY_ALL_PACKAGES 權(quán)限。

.如果應(yīng)用的target< 30郭变,是兼容之前的邏輯颜价;

.如果應(yīng)用的target>=30涯保,必須要申請(qǐng)android.permission.QUERY_ALL_PACKAGES這個(gè)權(quán)限, 才能查詢所有應(yīng)用。

注意:如果您的應(yīng)用以 Android 10(API 級(jí)別 29)或更低版本為目標(biāo)平臺(tái)周伦,那么全部應(yīng)用均會(huì)自動(dòng)對(duì)您的應(yīng)用可見(jiàn)夕春。

應(yīng)用安裝卸載廣播,仍然受軟件包可見(jiàn)性影響:

如果監(jiān)聽(tīng)安裝/卸載的應(yīng)用不符合可見(jiàn)性原則专挪,或者未聲明QUERY_ALL_PACKAGES權(quán)限, onReceive將不會(huì)回調(diào)及志。

廣播回調(diào)接口受影響

4.默認(rèn)授權(quán)

手機(jī)第一次開(kāi)機(jī)或者fota升級(jí)后第一次開(kāi)機(jī)進(jìn)行的默認(rèn)授權(quán):

系統(tǒng)預(yù)置的默認(rèn)授權(quán)機(jī)制,在Pms systemReady里面會(huì)根據(jù)Build.FINGERPRINT來(lái)判斷是不是第一次開(kāi)機(jī)寨腔,來(lái)做默認(rèn)授權(quán)速侈。

  1. share systemuid默認(rèn)授權(quán)權(quán)限(一般是在Manifest中配置類(lèi)似的
    android:sharedUserId=”android.uid.system”)
  2. 系統(tǒng)特權(quán)應(yīng)用并且是persistent進(jìn)行默認(rèn)授權(quán)危險(xiǎn)權(quán)限;
  3. 系統(tǒng)默認(rèn)應(yīng)用進(jìn)行局部權(quán)限授權(quán)(例如:開(kāi)機(jī)向?qū)嚷⑾鄼C(jī)倚搬、下載的Provider等)

原生機(jī)制第一次開(kāi)機(jī)默認(rèn)授權(quán)類(lèi):

./frameworks/base/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java

public  void grantDefaultPermissions(int userId)  {

grantPermissionsToSysComponentsAndPrivApps(userId); ---授權(quán)系統(tǒng)&特權(quán)應(yīng)用

grantDefaultSystemHandlerPermissions(userId); --- 授權(quán)默認(rèn)應(yīng)用

}
系統(tǒng)默認(rèn)授權(quán)應(yīng)用

新應(yīng)用第一次安裝授權(quán):

應(yīng)用安裝會(huì)走Pms,應(yīng)用安裝的過(guò)程中Pms會(huì)根據(jù)應(yīng)用聲明權(quán)限的level(Normal乾蛤、Dangerous每界、Signature),來(lái)決定是否允許應(yīng)用使用該權(quán)限家卖。

Normal:只要應(yīng)用申請(qǐng)眨层,就允許應(yīng)用使用該權(quán)限;

Signature:判斷該應(yīng)用簽名是否和平臺(tái)簽名一樣篡九,如果一樣就允許否則不允許使用該權(quán)限谐岁;

Dangerous:不給應(yīng)用授予該權(quán)限,需要應(yīng)用在用的時(shí)候動(dòng)態(tài)申請(qǐng)?jiān)摍?quán)限榛臼。

5.AppOps機(jī)制

AppOps全稱是Application Operations伊佃,類(lèi)似我們平時(shí)常說(shuō)的應(yīng)用程序的操作(權(quán)限)管理。Google從4.3開(kāi)始推出Appops, 在Settings里面未開(kāi)放Appops的入口沛善,但這套方案卻一直在后臺(tái)默默的運(yùn)行著航揉。

涉及的類(lèi):

android.app.AppOpsManager

com.android.server.AppOpsService

配置文件:appops.xml

appops.xml位于/data/system/目錄下,存儲(chǔ)各個(gè)app的權(quán)限設(shè)置和操作信息金刁。

Android提供了命令行的方式來(lái)更改某個(gè)應(yīng)用的某個(gè)權(quán)限帅涂,進(jìn)入adb shell可以查看相應(yīng)用法:

appops命令

AppOps權(quán)限檢查流程:

appops檢查權(quán)限流程

6. Selinux權(quán)限介紹

為什么增加Selinux?

進(jìn)程理論上所擁有的權(quán)限與執(zhí)行它的用戶的權(quán)限相同尤蛮。比如媳友,以root用戶啟動(dòng)FileManager,那么FileManager就有root用戶的權(quán)限产捞,在Linux系統(tǒng)上能干任何事情醇锚。也就是像4.4以前的版本,只要我們對(duì)結(jié)點(diǎn)給予足夠的權(quán)限,就可以隨意的進(jìn)行任意的操作焊唬。

Linux DAC有明顯的不足恋昼,其中一個(gè)重要點(diǎn)就是,Root權(quán)限幾乎可以做任意事情赶促,一旦入侵者拿到root權(quán)限液肌,即已經(jīng)完全掌控了系統(tǒng)。另外每一個(gè)進(jìn)程默認(rèn)都拿到對(duì)應(yīng)這個(gè)用戶的所有權(quán)限鸥滨,可以改動(dòng)/刪除這個(gè)用戶的所有文件資源嗦哆,明顯這個(gè)難以防止惡意軟件。所以在DAC之外設(shè)計(jì)了一個(gè)新的安全模型婿滓,叫MAC(Mandatory Access control)吝秕,強(qiáng)制性訪問(wèn)控制,即系統(tǒng)針對(duì)每一項(xiàng)訪問(wèn)都進(jìn)行嚴(yán)格的限制空幻,具體的限制策略由開(kāi)發(fā)者給出烁峭。MAC:即任何進(jìn)程想在SELinux系統(tǒng)中干任何事情,都必須先在安全策略配置文件中賦予權(quán)限秕铛。凡是沒(méi)有出現(xiàn)在安全策略配置文件中的權(quán)限约郁,進(jìn)程就沒(méi)有該權(quán)限。

打開(kāi)和關(guān)閉selinux功能:

出現(xiàn)了selinux相關(guān)的權(quán)限拒絕但两,則在kernel log 或者android log中都有對(duì)應(yīng)的”avc: denied”鬓梅,當(dāng)然也可能和selinux的模式有關(guān)系,我們需要首先要確認(rèn)當(dāng)時(shí)SELinux 的模式, 是enforcing mode 還是 permissve mode谨湘。

如果問(wèn)題容易復(fù)現(xiàn)绽快,我們可以先將SELinux 模式調(diào)整到Permissive mode,然后再測(cè)試確認(rèn)是否與SELinux 約束相關(guān)紧阔。

可以通過(guò)以下命令設(shè)置:

adb shell setenforce 0

setenforce 0 設(shè)置SELinux 成為permissive模式 臨時(shí)關(guān)閉selinux

setenforce 1 臨時(shí)打開(kāi)selinux

如何配置selinux權(quán)限:

例如報(bào)如下錯(cuò)誤:

TcmReceiver: type=1400 audit(0.0:4214): avc: denied { write } for name="tcmd" dev="tmpfs" ino=1301 scontext=u:r:remote_prov_app:s0:c162,c256,c512,c768 tcontext=u:object_r:vendor_dpmtcm_socket:s0 tclass=sock_file permissive=0 app=com.android.remoteprovisioner

具體參數(shù)表示:

權(quán)限: avc: denied { write } 表示缺少write權(quán)限

哪個(gè)te文件缺少權(quán)限: scontext=u:r:remote_prov_app:s0:c162,c256,c512,c768 ---- remote_prov_app缺少權(quán)限

哪個(gè)文件缺少權(quán)限: tcontext=u:object_r:vendor_dpmtcm_socket:s0 ---- remote_prov_app缺少對(duì)vendor_dpmtcm_socket的權(quán)限配置

文件類(lèi)型:  tclass=sock_file 權(quán)限文件類(lèi)型

表達(dá)含義:remote_prov_app文件需要新增類(lèi)型為sock_file的vendor_dpmtcm_socket的write權(quán)限坊罢。

如何修改:配置te文件,添加 tclass=sock_file,編譯selinux_policy擅耽,把system/ect下面的selinux文件夾活孩,push到手機(jī)syste/ect進(jìn)行覆蓋。然后重啟驗(yàn)證修改是否生效乖仇。

注:不要修改neverallow憾儒,會(huì)導(dǎo)致CTS測(cè)試失敗。如果修改了file_contexts,替換selinux是不生效的乃沙。因?yàn)?標(biāo)文件的context已經(jīng)?成了起趾,替換selinux并不會(huì)重新給?標(biāo)文件設(shè)置context。這時(shí)可以通過(guò)chcon命令?動(dòng)修改context警儒。

參考文章:
  1. 「Android 安全架構(gòu)」你真的了解權(quán)限機(jī)制嗎训裆?http://www.reibang.com/p/a17c8bed79d9
  2. 「 Android 沙箱機(jī)制」 https://blog.csdn.net/fei20121106/article/details/84023953
  3. 「 Android 安全架構(gòu)及權(quán)限控制機(jī)制剖析」http://www.uml.org.cn/mobiledev/201303281.asp
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子缭保,更是在濱河造成了極大的恐慌,老刑警劉巖蝙茶,帶你破解...
    沈念sama閱讀 218,036評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艺骂,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡隆夯,警方通過(guò)查閱死者的電腦和手機(jī)钳恕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蹄衷,“玉大人忧额,你說(shuō)我怎么就攤上這事±⒖冢” “怎么了睦番?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,411評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)耍属。 經(jīng)常有香客問(wèn)我托嚣,道長(zhǎng),這世上最難降的妖魔是什么厚骗? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,622評(píng)論 1 293
  • 正文 為了忘掉前任示启,我火速辦了婚禮,結(jié)果婚禮上领舰,老公的妹妹穿的比我還像新娘夫嗓。我一直安慰自己,他們只是感情好冲秽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布舍咖。 她就那樣靜靜地躺著,像睡著了一般锉桑。 火紅的嫁衣襯著肌膚如雪谎仲。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,521評(píng)論 1 304
  • 那天刨仑,我揣著相機(jī)與錄音郑诺,去河邊找鬼。 笑死杉武,一個(gè)胖子當(dāng)著我的面吹牛辙诞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播轻抱,決...
    沈念sama閱讀 40,288評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼飞涂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起较店,我...
    開(kāi)封第一講書(shū)人閱讀 39,200評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤士八,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后梁呈,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體婚度,經(jīng)...
    沈念sama閱讀 45,644評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評(píng)論 3 336
  • 正文 我和宋清朗相戀三年官卡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蝗茁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,953評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡寻咒,死狀恐怖哮翘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情毛秘,我是刑警寧澤饭寺,帶...
    沈念sama閱讀 35,673評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站叫挟,受9級(jí)特大地震影響佩研,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜霞揉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評(píng)論 3 329
  • 文/蒙蒙 一旬薯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧适秩,春花似錦绊序、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,889評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至扬跋,卻和暖如春阶捆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背钦听。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,011評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工洒试, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人朴上。 一個(gè)月前我還...
    沈念sama閱讀 48,119評(píng)論 3 370
  • 正文 我出身青樓垒棋,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親痪宰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叼架,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容