1. 课程导入
Android 是全球装机量最大的移动操作系统,其安全设计并非单一机制,而是由应用沙箱、权限模型、应用签名、SELinux、Verified Boot、密钥库等多层防线共同构成的纵深防御体系。在这套体系中,权限模型处在“应用与系统资源之间的第一道闸门”位置:它决定了应用能访问哪些数据、能调用哪些能力、以什么身份与系统服务交互。理解权限模型,是理解 Android 安全工程其他所有主题的前提。
一、Android 安全概况:从“开放”到“可控”
Android 的安全模型建立在 Linux 内核之上,每个应用默认运行在独立的 UID 与独立进程空间中,形成应用沙箱。沙箱解决了“应用之间默认隔离”的问题,但移动应用天然需要访问相机、位置、通讯录、存储、网络等共享资源,于是系统必须提供一套受控的授权机制,这就是权限模型存在的根本原因。
从 Android 6.0(API 23)开始,权限模型从“安装时一次性授权”演进为运行时权限;从 Android 10 开始,存储访问被分区存储(Scoped Storage)重构;Android 11 引入一次性授权与自动重置;Android 12 增加大致位置与精确位置分离;Android 13 将通知、媒体读取进一步细分为独立权限。这条演进主线说明:Android 权限模型持续朝着最小权限、用户可控、按需授权、可撤销的方向收敛。
二、权限模型为什么重要
权限模型的重要性可以从三个视角理解。
- 用户视角:权限是隐私的可视化边界。用户通过权限授予与撤销,决定应用能否读取位置、照片、麦克风等敏感数据。
- 开发者视角:权限声明与申请方式直接影响应用能否上架、能否在后台稳定运行、能否通过 Google Play 政策审核。错误声明高危权限或过度申请权限,会导致审核拒绝或用户流失。
- 系统安全视角:权限是攻击面收敛的关键。攻击者一旦通过漏洞绕过权限检查,就可能实现越权访问、数据窃取或提权。因此权限校验点、系统服务入口、Binder 调用边界都是安全审计的重点。
下面这张图展示了 Android 权限模型在整体安全架构中的位置:应用层发起请求,框架层进行权限校验,内核层通过 UID、SELinux 等机制执行强制约束。
三、核心原理:权限模型的三层校验
Android 权限校验通常发生在三个层面,理解这三层有助于定位“权限申请了却仍然失败”的问题。
- 声明层:应用在 AndroidManifest.xml 中通过
<uses-permission>声明所需权限。普通权限安装即授予,危险权限必须运行时申请。 - 框架层:系统服务在关键 API 入口调用
checkPermission()或enforcePermission(),校验调用方 UID 是否被授予对应权限。 - 内核层:即使框架层放行,SELinux 仍可能基于进程域与文件标签拒绝访问,形成第二道强制约束。
一个典型的权限校验失败日志如下,可以看到框架层与内核层分别给出拒绝信息:
// 框架层拒绝:调用方缺少权限
java.lang.SecurityException: Permission Denial:
starting Intent { act=android.intent.action.CALL } from pid=12345
requires android.permission.CALL_PHONE
// 内核层拒绝:SELinux 策略不允许
avc: denied { read } for pid=12345 comm="app_process"
scontext=u:r:untrusted_app:s0 tcontext=u:object_r:system_data_file:s0
tclass=file permissive=0
adb shell dumpsys package <包名> 查看 grantedPermissions,并用 adb logcat | grep avc 检查是否存在 SELinux 拒绝。
四、案例场景:一个“位置权限”引发的三类问题
假设一个外卖类应用需要获取用户位置。开发团队可能遇到以下场景:
| 场景 | 现象 | 根因 | 处理方式 |
|---|---|---|---|
| 未声明权限 | 调用定位 API 直接抛 SecurityException | Manifest 缺少 ACCESS_FINE_LOCATION | 补充声明并重新安装 |
| 未运行时申请 | API 返回空位置或权限回调被拒 | 危险权限未走 requestPermissions 流程 | 在合适时机发起运行时申请 |
| 后台定位受限 | 应用退到后台后位置更新停止 | Android 10+ 后台定位需单独权限与前台服务 | 申请 ACCESS_BACKGROUND_LOCATION 并声明前台服务类型 |
这个案例说明:权限问题往往不是“一个开关”,而是声明、申请、使用时机、系统版本差异共同作用的结果。只盯着代码中的一行申请语句,很容易误判。
五、常见误区与复盘
- 误区一:权限申请越多越保险。过度申请高危权限会触发应用商店审核风险,也会降低用户信任。应遵循最小权限原则。
- 误区二:用户拒绝一次就永久拒绝。Android 允许用户多次拒绝,开发者应提供解释性 UI,而不是反复弹窗骚扰。
- 误区三:权限授予等于数据可随意使用。即使获得权限,仍需遵守分区存储、后台限制、隐私政策与平台合规要求。
- 误区四:只关注应用层,忽略系统层。很多“权限正常但访问失败”的问题,根因在 SELinux、文件标签或系统服务策略。
六、课程目标与学习路径
本课程围绕“Android 权限模型与系统安全工程”展开,目标是让学习者具备三项能力:
- 理解能力:掌握权限分类、权限组、运行时授权、签名权限、AppOps、SELinux 等核心概念及其关系。
- 实践能力:能够正确声明与申请权限,处理拒绝与撤销场景,使用 adb、dumpsys、logcat 等工具定位权限问题。
- 工程能力:能够从安全架构视角评估权限设计,识别越权风险,理解系统完整性校验与密钥库等配套机制。