你真的了解Android權限機制嗎?@3

      網友投稿 1024 2025-03-31

      接上文https://www.epubit.com/selfpublish/article/6093 @1 https://www.epubit.com/selfpublish/article/6096 @2  敏詞shen查太坑人了,代碼里不能有小寫ID,比如pID,uID什么的。還有SettingBase代碼中不可連用,以基地代替,只能拆著發  2. 框架層

      因為 ANDROID 6.0 之前組件不能在運行時改變權限,所以系統的權限檢查執行過程是靜態的。這個情況下,組件的角色和權限的等安全屬性會被放置在元數據中,即 ANDROIDMANIFEST.XML 文件中,而不是組件的本身。系統包管理器會負責記錄組件的權限,所以靜態權限檢查可以從包管理器拿到權限,由運行環境或容器來執行權限檢查,這樣子可以把業務邏輯和安全決策分離開來,但是靈活性不足。

      那 ANDROID 組件可不可以不預先聲明權限在 ANDROIDMANIFEST.XML 中呢?答案是:可以的。ANDROID 的動態權限執行,可以讓組件自身執行權限檢查,而不是運行環境。

      所以接下來我們將深入了解框架層的動態和靜態權限執行的原理。

      動態權限執行

      動態權限執行,最典型的場景,就是 IPC。ANDROID 的核心系統服務統一會注冊到服務管理器,任何應用,只要知道服務的注冊名稱,就可以拿到對應的 BINDER引用,就可使用 BINDER IPC 機制調用服務。因為 BINDER 沒有內置的訪問控制機制,所以每個系統服務需要自己實現訪問控制機制。

      系統服務可以直接檢查調用者的 uID,通過限定 uID 來控制訪問權限,這種方式簡單直接,但是對于非固定uID的應用,就比較棘手了。而且大部分服務,并不關心調用者的 uID,只需要檢查調用者是否被賦予特定的權限即可。所以這種方式,比較適合只允許以 ROOT(uID:0) 或 SYSTEM(uID:1000) 運行的進程訪問的服務檢查。

      那換一種方式,服務怎么拿到調用者的權限列表?我們知道,大部分 uID 都是和包一一對應的,除了共享 uID。(共享 UID 后面再詳細解釋)

      使用 Binder.getCallingUid() 和 Binder.getCallingPid() 獲取調用者的 UID 和 PID,通過 UID 在包管理器中查詢到對應應用的權限。android.content.Context 類中就有 checkPermission(String permission, int pid, int uid) 方法。實質上會調用到 PMS 中的 checkUidPermission(String perName, int uid),如下:

      Android 6.0 以下 PMS 中的 checkUidPermission(String perName, int uid)

      Android 6.0 以下的 checkUidPermission() 方法比較簡單,首先,基于入參 uid 獲取應用的 appId,拿到權限列表對象(也就是 packages.xml 里的 ? 映射),如果 GrantedPermissions 類中的 grantedPermissions 集合包含目標權限,則檢查通過。

      如果沒有該 GrantedPermissions 對象,則檢查目標權限是否可以被自動授予,實際上 mSystemPermissions 就是 platform.xml 文件中的 ? 標簽映射緩存,記錄了一些系統級應用的 uid 對應的 permission。例:   ...

      Android 6.0 及以上 PMS 中的 checkUidPermission(String perName, int uid)

      你真的了解Android權限機制嗎?@3

      可以注意到,6.0 之后 checkPermission() 方法有所改變。多了從 mSettings.mPermissions 去查詢權限列表。關鍵就在于這個 mSettings 里面保存的這個 SettingBase 對象,它記錄了 PermissionsState 也就是權限的授予情況。

      所以檢查權限的流程是本來就有的,6.0 之后差異僅在于:危險級別權限可以動態修改授權情況,也就是修改 PermissionState 的 mGranted 值,所以每次權限執行,都會查詢下 mGranted 值。

      靜態權限執行

      靜態權限執行的典型場景,是跨應用組件交互。我們使用隱式 Intent 來表達意圖,搜索匹配的組件,如果有多個,彈出選擇框,目標組件被選定后,會由 ActivityManagerService 執行權限檢查,檢查目標組件是否有相應的權限要求,如果有,則把權限檢查的工作交給 PMS,去檢查調用者有沒有被授權這些權限。

      接下來的總體的流程和動態執行流程大致相同:Binder.getCallingUid()和Binder.getCallingPid()獲取調用者的 UID 和 PID,然后利用 UID 映射包名,再獲得相關權限集合。如果權限集合中含有所需權限即啟動,否則拋出 SecurityException 異常。靜態權限執行這里,我們可以詳細了解下,每種組件的權限檢查時機和具體順序是怎么樣的。

      組件權限執行

      思考一下,什么時候會執行對調用者的權限檢查?那肯定是在目標組件被調用的時候,去解析目標組件聲明的權限,如果有,就執行權限檢查。

      Activity 和 Service。Activity 顯而易見,會在 startActivity() 和 startActivityForResult() 里解析到聲明權限的 Activity 時,就執行權限檢查。而 Service startService()、stopService() 和 bindService(),這 3 個方法被調用時都會進行權限檢查。

      廣播。我們注意到,發送廣播除了常用的 sendBroadcast(Intent intent),還有個 sendBroadcast(Intent intent, String receiverPermission),該方法可以要求廣播接受者具備特定的權限,但是,調用 sendBroadcast 是不會進行權限檢查的,因為廣播是異步的,所以權限檢查會在 intent 傳遞到已注冊的廣播接受者時進行,如果接收者不具備特定的權限,則不會接收到該廣播,也不會收到 SecurityException 異常。

      反過來,接收者可以要求廣播發送者必須具備的權限,所要求的權限在 manifest 文件中設置 ? 標簽的 permission 屬性,或者動態注冊時指定 registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler),權限檢查也是在廣播傳遞時執行。

      所以,收發廣播可以分開指定權限。值得一提的是,一些系統廣播被聲明為 protected,并且只能由系統進程發送,比如 PACKAGE_INSTALLED。只能由系統進程發送,這個限制會在內核層進行檢查,對調用者的 UID 進行匹配,只能是 SYSTEM_UID、PHONE_UID、SHELL_UID、BLUETOOTH_UID 或 root。如果其他 UID 的進程試圖發送系統廣播,則會收到 SecurityException 異常。

      想了解所有的系統廣播,可以打開/system/framework/framework-res.apk 中的 AndroidManifest.xml ? 標簽詳細了解。   ContentProvider。ContentProvider 可以為讀寫分別指定不同的權限,即:調用目標 provider、query() 方法 和 insert()、update()、delete() 都會進行權限檢查。

      總結

      綜上所述,Android 的權限的檢查會在各個層次上實施。

      高層的組件,例如應用和系統服務,通過包管理器查詢應用程序被賦予的權限,并決定是否準予訪問。

      低層的組件,通常不訪問包管理器,比如本地守護進程,依賴于進程的 UID、GID 和補充 GID 來決定賦予。

      訪問系統資源時,如設備文件、UNIX 域套接字和網絡套接字,則由內核根據所有者、目標資源的訪問權限和訪問進程的進程屬性或者 packages.list 來進行控制。

      共享 UID

      最后簡單說下共享 UID,填一下前面挖的坑。雖說 Android 會為每一個應用分配唯一的 UID,但如果應用使用相同的密鑰簽發,就可以使用相同 UID 運行,也就是運行在同一個進程中。

      這個特性被系統應用和核心框架服務廣泛使用,比如:Google Play 和 Google 定位服務,請求同一進程內的 Google 登錄服務,從而達到靜默自動同步用戶數據的體驗。

      值得注意的是:Android 不支持將一個已安裝的應用,從非共享 UID 切換到共享狀態,因為改變了已安裝應用的 UID,會導致應用失去對自己文件的訪問權限(在一些早期 Android 版本中),所以如果使用共享 UID 必須從一開始就設計好。

      本文轉載自異步社區

      任務調度 Android

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:截圖方法,電腦如何截屏截圖,電腦截屏的8種截圖方式
      下一篇:excel2003按名字排序的教程
      相關文章
      亚洲色大成网站www永久男同 | 色偷偷女男人的天堂亚洲网| 久久噜噜噜久久亚洲va久| 亚洲欧洲无码AV电影在线观看| 亚洲精品色婷婷在线影院| 亚洲成AⅤ人影院在线观看| 亚洲成在人线aⅴ免费毛片| 亚洲精华国产精华精华液网站| 久久亚洲国产最新网站| 亚洲 日韩经典 中文字幕| 亚洲大成色www永久网址| 国产成人精品日本亚洲18图| 亚洲乱码在线卡一卡二卡新区| 亚洲第一男人天堂| 亚洲6080yy久久无码产自国产| 亚洲av日韩aⅴ无码色老头| 国产AV无码专区亚洲AV蜜芽| 无码不卡亚洲成?人片| 久久国产成人亚洲精品影院| 久久久久亚洲?V成人无码| 伊人亚洲综合青草青草久热| 亚洲线精品一区二区三区影音先锋 | 国产精品亚洲一区二区在线观看 | 久久亚洲精品高潮综合色a片| 亚洲AV性色在线观看| 亚洲国产精品13p| 久久亚洲2019中文字幕| 亚洲国产无套无码av电影| 亚洲AV乱码一区二区三区林ゆな| 亚洲激情中文字幕| 亚洲天堂一区二区三区| 亚洲 日韩 色 图网站| 国产av无码专区亚洲av毛片搜| 爱情岛论坛网亚洲品质自拍| 人人狠狠综合久久亚洲88| 99久久亚洲精品无码毛片| 狠狠色香婷婷久久亚洲精品| 亚洲av无码无线在线观看| 亚洲人成色7777在线观看不卡| 亚洲女久久久噜噜噜熟女| 久久青青草原亚洲av无码app|