## 1. 防截屏输入组件需求分析:安全场景、合规要求、用户隐私保护、防截屏能力边界 ### 1.1 业务安全场景与攻击链路 在移动金融、政务、医疗等高敏场景中,输入组件常成为数据泄露的突破口。攻击者不依赖 Root 权限即可通过系统截屏、录屏、无障碍服务或第三方键盘侧录等手段获取用户输入。以下表格梳理典型场景及对应威胁: | 场景 | 威胁 | 攻击者能力 | 典型触发点 | |------|------|-----------|-----------| | 手机银行密码输入 | 恶意应用通过 `SurfaceControl.screenshot()` 截获密码 | 无 Root,仅需 `SYSTEM_ALERT_WINDOW` 权限 | 登录/转账密码框 | | 在线支付动态验证码 | 屏幕共享软件(如 TeamViewer QuickSupport)录制验证码 | 用户授权屏幕共享 | 验证码输入框 | | 政务 APP 实名认证 | 无障碍服务模拟点击并逐字读取输入内容 | 后台无障碍服务(如恶意输入法) | 身份证号输入框 | | 病历数据录入 | 第三方键盘侧录按键时序与字符序列 | 输入法应用具有 `BIND_INPUT_METHOD` | 电子病历备注栏 | 核心攻击链路可抽象为下图: 防截屏输入组件攻击链路与防御边界 用户输入 安全键盘/输入框 恶意应用 截屏/录屏/无障碍 外部存储/网络 数据泄露出口 防御边界:FLAG_SECURE + 安全输入法 + 手势防录 + 运行态检测 合规要求 GB/T 35273-2020 个人信息安全规范 App隐私政策中需明确截屏防护声明 用户隐私保护 输入内容不落日志、不共享剪贴板 仅存活期内存,Activity销毁即清除 ### 1.2 防截屏能力边界 Android 平台原生防截屏主要通过 `WindowManager.LayoutParams.FLAG_SECURE` 实现。但其能力存在明确边界:
FLAG_SECURE 仅阻止系统截屏/录屏,不阻止以下三类侧录:
▪ 无障碍服务逐字读取(AccessibilityEvent)
▪ 第三方输入法按键内容缓存
▪ 磁贴/悬浮窗覆盖后的硬件截屏(如某些出厂自带截屏)
在 Compose 中设置 FLAG_SECURE 的典型代码:
// 在 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 以上仍可通过 TYPE_VIEW_TEXT_CHANGED 获取字符变化)。

陷阱 2:在 Dialog、Popup、WindowInsets 覆盖层上忘记设置 FLAG_SECURE。每个独立 Window 都必须单独设置。

陷阱 3:使用 SecureRandom 做混淆后认为无法破解,但攻击者仍可通过屏幕像素对比推断按键位置。
### 1.6 本章知识结构检查表 | 知识点 | 掌握要求 | 对应后续章节 | |-------|---------|------------| | 攻击链路与边界图 | 理解 | 第 2 章详细技术选型 | | FLAG_SECURE 代码设置 | 编写 | 第 3 章 Compose 集成 | | 无障碍服务绕过机制 | 意识到风险 | 第 4 章自定义 View 防范 | | 合规声明撰写 | 应用 | 第 5 章隐私政策适配 | | 初代常见错误 | 避免 | 第 6 章调试与验证 | 本章定位为全课程的“安全基线”,后续所有实现均围绕此处定义的边界与合规要求展开。开发者在进入代码阶段前,应依据此需求分析完成安全风险评估与合规自查清单。