隐私合规与权限治理
“在强监管时代,因为隐私合规不达标导致 App 被全面下架的惨痛教训比比皆是。合规不再是边角料工作,而是生命线工程。”
面试策略: 结合你 SDK 开发的经历,强调你在收拢采集入口、治理第三方 SDK 以及设备标识符(OAID 等)演进上的经验。
一、隐私合规的“生死红线“
国内工信部和网信办、海外的 GDPR 对隐私保护的底线要求非常严苛,核心原则是:未经同意,不取一毫;最小必要,严禁滥用。
- 隐私弹窗: 用户首次打开 App 时,必须弹窗展示《隐私政策》和《用户协议》,在用户点击“同意“之前,绝对不允许执行任何代码去读取敏感信息或初始化敏感 SDK。
- 默认勾选: 注册/登录页面的协议同意框,绝不能默认帮用户打勾。
- 超范围收集: 不能因为是一个手电筒 App 就要求读取通讯录和位置信息,这违反“最小必要“原则。
- 频次限制: 不允许在后台高频次地(如每秒一次)获取用户位置或读剪切板。
二、Android 权限治理演进
Android 系统本身的权限管理也顺应合规趋势,逐年收紧:
| 权限变化里程碑 | 影响与适配策略 |
|---|---|
| Android 6.0 动态权限 | 危险权限(相机、位置等)不能在安装时一揽子授权,必须在使用时动态弹窗申请。 |
| Android 10 分区存储 | 限制对 SD 卡的粗放读取。App 只能自由读取自己的目录和媒体库(通过 MediaStore),读取其他文件需请求特定授权。 |
| Android 11 单次授权 | 引入“仅限这一次”选项。App 进入后台后,该权限可能被系统立刻收回。代码里不能缓存授权状态,每次使用前都要检查。 |
| Android 12 近似位置 | 用户可以选择只给你“大致位置”(精确度几平方公里)而不是 GPS 坐标。位置功能必须兼容这种精度。 |
| Android 13 通知权限 | 发通知不再是默认开启的,需要显式申请 POST_NOTIFICATIONS 权限。 |
| Android 14 媒体部分授权 | 允许用户只授权照片库中的“几张指定图片”,而不是全量相册读取权限。 |
三、设备标识符的演变与 OAID
作为做设备指纹出身的开发者,这块是你的强项:
- MAC 地址 / IMEI: 曾经用来唯一追踪用户的神器。随着隐私收紧,Android 10 以后非系统级应用彻底无法获取真实的 IMEI 和全局不变的 MAC 地址(系统返回全 0 或抛出异常)。
- Android ID: 恢复出厂设置或签名改变会发生变化。在 Android 8.0 之后,不同的 App 读到的同一个设备的 Android ID 甚至是不一样的(基于签名的作用域隔离)。
- OAID (匿名设备标识符):
- 国内由于 Google 服务的缺失,由移动安全联盟 (MSA) 推出的替代方案。
- 特性:用户可以在系统设置中手动重置 OAID。
- 它满足了广告归因的需求,又给了用户重置追踪的权利,是目前国内合规体系下获取设备标识的主流手段。
四、第三方 SDK 合规治理
因为第三方 SDK 的违规采集导致主 App 被下架,这叫“背锅”。所以大型 App 会对接入的 SDK 进行严苛治理。
- 延迟初始化: 所有第三方 SDK(尤其是广告、推送、统计、风控)的初始化动作,必须放在隐私弹窗“同意”按钮的回调之后。
- 采集点收口: 收拢项目里的定位、剪切板、设备信息读取入口,封装成统一的 Manager 代理。在 Manager 中增加鉴权、缓存、频次控制和合规拦截。
- 静态扫描与字节码 Hook:
- 对于不受控的第三方 SDK 或陈旧的 Jar 包,在打包阶段(或运行时阶段,利用 ASM 插件 或类似 Epic 的机制),对
TelephonyManager.getDeviceId()等敏感 API 调用进行 Hook 或替换,在未同意隐私政策时返回空数据。
- 对于不受控的第三方 SDK 或陈旧的 Jar 包,在打包阶段(或运行时阶段,利用 ASM 插件 或类似 Epic 的机制),对
五、敏感行为的安全保障
- 剪切板滥用:
- iOS 14 和 Android 12 开始,App 读取剪切板系统会在顶部弹出明显提示。
- 如果应用为了淘口令等功能无脑轮询读取剪切板,会让用户极其反感甚至遭遇投诉。正确做法是切前台时且发现特定格式的文本才进行解析。
- 日志安全 / 脱敏:
- 本地日志绝不允许明文打印用户的手机号、身份证、真实姓名、密码。必须进行脱敏(如
138****1234)或强加密。
- 本地日志绝不允许明文打印用户的手机号、身份证、真实姓名、密码。必须进行脱敏(如
- 权限被拒处理:
- 不能因为用户拒绝了位置权限,就不让用户使用“扫一扫”功能,不能搞权限捆绑。
高频面试题
Q1: 在用户点击同意隐私政策前,App 到底能不能访问网络? 不能。任何网络请求都会向外暴露用户的 IP 地址等基础设备信息,因此在严格合规要求下,在隐私弹窗同意前,不允许发起任何向外部的请求,更不能拉起各种后台 Service 提前预热 SDK。
Q2: 怎么防止项目中接入的第三方广告 SDK 在后台偷读用户剪切板或位置信息?
- 商务层面: 选用正规、经过官方审核的版本,并在应用内隐私政策明确披露该 SDK。
- 工程层面: 不在后台启动和保活该 SDK 所在的组件;通过 ASM 字节码插桩,在打包期间将该 SDK 调用敏感 API 的方法替换为我们自己的代理方法,在代理中加入合规状态判断和频次拦截。
Q3: Android 10+ 无法获取 IMEI 后,风控和广告归因怎么做? 国内推荐使用 MSA 提供的 OAID 库获取匿名设备标识;海外使用 Google Advertising ID (AAID)。同时,风控系统转为采用弱特征组合设备指纹(通过分辨率、系统版本、传感器特征等计算生成),不再依赖单一的绝对不变标识符。
易错点 / 追问
- 粗暴对待权限拒绝: 用户拒绝权限后不断弹窗骚扰,或者直接
finish()应用,这会导致极差体验并被商店警告。 - 缓存单次授权状态: 在 Android 11+ 把获得的权限记录在
SharedPreferences中,下次直接用,结果权限已被系统回收导致崩溃。 - 过度索权: 开发图省事,不管用不用,先把
Manifest里的权限申请一大堆,上架时很容易被拒。