FLAG_SECURE 仅阻止系统截屏/录屏,不阻止以下三类侧录:
▪ 无障碍服务逐字读取(AccessibilityEvent)
▪ 第三方输入法按键内容缓存
▪ 磁贴/悬浮窗覆盖后的硬件截屏(如某些出厂自带截屏)
在 Compose 中设置 FLAG_SECURE 的典型代码:
▪ 无障碍服务逐字读取(AccessibilityEvent)
▪ 第三方输入法按键内容缓存
▪ 磁贴/悬浮窗覆盖后的硬件截屏(如某些出厂自带截屏)
// 在 Activity 或 Compose WindowCompat 中设置
class SecureInputActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
setContent {
SecureInputTheme {
PasswordInputField() // 自定义安全输入组件
}
}
}
}
// 针对 Compose 独立窗口(如 Dialog)需单独设置
Dialog(onDismissRequest = { /* ... */ }) {
// Dialog 自动继承父窗口 FLAG_SECURE?不!
// Android 11+ 中 Dialog Window 需手动添加
val dialogWindow = (LocalContext.current as ComponentActivity).window
// 但更可靠方式是使用 Dialog(ownerActivity = ...) 并手动设置
}
### 1.3 合规与隐私保护要求
根据《个人信息安全规范》及 App 隐私合规审核实践,防截屏输入组件需满足以下硬性要求:
- 输入内容不可被任何系统服务捕获:除目标 Activity 外,截屏、录屏、无障碍事件均不能获取明文。
- 键盘不可留存输入记录:若使用系统键盘需关闭预测、自动纠错和用户词典;推荐使用定制安全键盘。
- 日志与崩溃追踪中不得包含明文:
Log.d、Timber、Crashlytics等必须过滤敏感字段。 - Activity 被切到后台时自动清除输入缓存:在
onPause或onStop中清空MutableState数据。
【截屏防护说明】
本 App 在输入密码、验证码等敏感信息时,会通过系统安全标记(FLAG_SECURE)
保护您输入的内容不被截屏、录屏或其他应用恶意捕获。
同时,我们不会记录您输入的原始字符,所有输入仅存活于当前会话内存中。
### 1.4 安全场景强弱对比
| 防护维度 | FLAG_SECURE | 系统键盘(安全模式) | 定制安全键盘 |
|---------|------------|-------------------|------------|
| 防系统截屏 | ✅ | ❌(键盘可被截屏) | ✅(整体窗口防护) |
| 防无障碍侧录 | ❌ | ❌ | ✅(使用不可访问的 View) |
| 防第三方键盘缓存 | ❌ | ❌(系统键盘不缓存) | ✅(内存即时清) |
| 防录屏软件 | ✅(FLAG_SECURE 生效时) | ❌ | ✅ |
| 用户输入体验 | 原生体验 | 输入法切换可能出错 | 需额外开发按键布局 |
### 1.5 常见错误与初期决策陷阱
在项目初始阶段,开发者容易陷入以下误区:
陷阱 1:认为 FLAG_SECURE 能完全阻止无障碍服务。实际上 FLAG_SECURE 不影响无障碍事件分发(Android 10 以上仍可通过
陷阱 2:在 Dialog、Popup、WindowInsets 覆盖层上忘记设置 FLAG_SECURE。每个独立 Window 都必须单独设置。
陷阱 3:使用
### 1.6 本章知识结构检查表
| 知识点 | 掌握要求 | 对应后续章节 |
|-------|---------|------------|
| 攻击链路与边界图 | 理解 | 第 2 章详细技术选型 |
| FLAG_SECURE 代码设置 | 编写 | 第 3 章 Compose 集成 |
| 无障碍服务绕过机制 | 意识到风险 | 第 4 章自定义 View 防范 |
| 合规声明撰写 | 应用 | 第 5 章隐私政策适配 |
| 初代常见错误 | 避免 | 第 6 章调试与验证 |
本章定位为全课程的“安全基线”,后续所有实现均围绕此处定义的边界与合规要求展开。开发者在进入代码阶段前,应依据此需求分析完成安全风险评估与合规自查清单。
TYPE_VIEW_TEXT_CHANGED 获取字符变化)。陷阱 2:在 Dialog、Popup、WindowInsets 覆盖层上忘记设置 FLAG_SECURE。每个独立 Window 都必须单独设置。
陷阱 3:使用
SecureRandom 做混淆后认为无法破解,但攻击者仍可通过屏幕像素对比推断按键位置。