本节摘要:SOURCE 1.6/5.1:Android 靠应用沙箱、权限模型、SELinux、Keystore、Verified Boot 叠层防护。本节帮开发者「会用平台能力」而非重复造轮子。
每个 App 独立 Linux UID,/data/data/<package> 仅本进程可访问(非 root)。不要把密钥写 SD 卡公有目录。
Android 11+ 分区存储:其他 App 无法读你的 MediaStore 文件 unless 显式共享。
| 类型 | 示例 | 实践 |
|---|---|---|
| 安装时 | INTERNET | 最小声明 |
| 运行时 | CAMERA, LOCATION | rationale + 拒绝降级 |
| 特殊 | MANAGE_EXTERNAL_STORAGE | 商店审核极严 |
导出组件必须设 android:exported="false" 或 signature 权限保护。
SELinux 强制 MAC,限制进程即使 root 也常被 confine。开发者侧:不依赖 root 检测替代安全设计;Play Integrity 检测设备完整性(篡改、非 Play 安装)。
// Play Integrity 请求示例思路 integrityManager.requestIntegrityToken( IntegrityTokenRequest.builder().build() )
setUserAuthenticationRequired 绑定生物识别
| 机制 | 防什么 |
|---|---|
| 沙箱 | 跨 App 读数据 |
| Keystore | 密钥导出 |
| SELinux | 提权后横向 |
| Verified Boot | 系统被刷机 |
⚠️ 常见坑:
requestLegacyExternalStorage拖延分区存储适配 — Google 已逐步收紧。
💡 关键直觉:Android 安全 = Manifest 声明 + 运行时行为 + 服务端 三者一致。
下一节 iOS 对照:Keychain 与 ATS。
权限是移动数据的第一道门。原则是「最小声明、运行时说明、拒绝降级」:Manifest 只声明功能必需的权限;运行时请求带 rationale 说明用途;用户拒绝后降级功能而不是崩溃或频繁弹窗。位置、相机、通讯录这类敏感权限要特别谨慎——能不用权限实现(如用系统分享面板)就不用。
// 运行时权限带说明(示意) if (ContextCompat.checkSelfPermission(this, CAMERA) != GRANTED) { if (shouldShowRequestPermissionRationale(this, CAMERA)) { showRationale("用于扫码登录") // 先解释 } requestPermissions(arrayOf(CAMERA), REQ_CODE) }
Keystore 的正确用法是「密钥永不出设备」:App 把数据交给 Keystore 加密,拿到密文,解密也在 Keystore 内完成。配合生物识别绑定,还能要求解锁后的一次性操作。Play Integrity 用于风控辅助:检测设备完整性、安装来源、重打包,但它不是安全架构本身,服务端仍要独立鉴权。
| 能力 | 用途 | 常见误用 |
|---|---|---|
| UID 沙箱 | 数据隔离 | 明文写共享目录 |
| Keystore | 密钥保护 | 自存 key |
| Play Integrity | 风控信号 | 当唯一防线 |
| 分区存储 | 权限收敛 | 拖延适配 |
上线前按清单核对平台能力是否真正启用:应用沙箱正常(不写共享目录)、权限最小声明且运行时说明、导出组件全部设权限或非导出、Keystore 生成密钥且不可导出、分区存储已适配、调试与测试入口从生产包剥离、Play Integrity 接入并配合服务端校验。每项都能在几分钟内验证,是发布门禁的最小集合。平台机制是「地基」,但地基不阻止业务逻辑漏洞——服务端鉴权永远不能省略。
# Android 上线前核对(示例) [ ] allowBackup=false [ ] debuggable=false [ ] 所有导出组件有权限保护 [ ] 明文流量禁止 [ ] Token 走 Keystore 加密 [ ] 分区存储已适配
| 机制 | 启用方式 | 验证 |
|---|---|---|
| 沙箱 | 不写共享目录 | 检查路径 |
| Keystore | 生成不可导出密钥 | adb 不可读 |
| 分区存储 | 适配 Scoped Storage | 权限最小 |
| 完整性 | Play Integrity 接入 | 服务端验签 |
沙箱隔离的是进程,不是「你的 App 自己」。常见误用:把敏感数据明文写入公共目录(相册、下载目录)供其他 App 读取;用外部存储缓存 Token;通过 ContentProvider 暴露数据未加权限。修正原则:敏感数据一律在应用私有目录加密存储,对外共享走系统安全机制并最小化范围。误用往往不是「不知道沙箱」,而是「图省事」,评审时要专门检查这些「图省事」的痕迹。
平台安全机制随版本增强,升级要踩对节奏:新系统特性(分区存储、更严权限)按官方时间表适配,避免临期突击;最低支持版本要兼顾覆盖与安全,太老的系统缺少安全补丁且不支持新机制;安全补丁级别要纳入设备风控信号。版本策略不是纯技术决策,也是安全与覆盖率的权衡,需要在评审时明确记录。
平台机制(Keystore、Play Integrity、分区存储)解决的是「客户端侧」的信任问题,但它们与服务端是配合关系:Keystore 保护密钥,服务端仍要鉴权;Play Integrity 报告设备状态,服务端仍要决定是否信任;分区存储收敛权限,服务端仍要校验接口参数。记住平台机制的定位是「缩小攻击面、提高门槛」,而不是「替服务端做决策」。