Skip to content

42 · 移动应用安全与加固 ​

一句话定位:移动安全不是"加个混淆"就完事,而是一条纵深链:传输层(SSL Pinning)→ 存储层(安全存储)→ 代码层(混淆加固)→ 运行时(反调试)。对应前端的 08 · 前端安全,但移动端多了"逆向"这个威胁面。

开篇速览 ​

问题答案
前端对应物HTTPS/证书、XSS/CSRF、代码混淆、防调试
移动端独有威胁APK/IPA 可被解包逆向、证书中间人、root/越狱环境
最常被忽略密钥/密钥字符串硬编码在 Dart 里,混淆挡不住
一句话红线"混淆"是降低逆向成本的手段,不是安全边界;真正的密钥必须进原生安全存储,不进 Dart 源码

代码来源说明:HaierEnergy 使用 Dio 请求(见 09 篇),有证书配置痕迹;是否做 SSL Pinning 需按发布环境确认。 本篇给出通用纵深方案。


一、纵深防御四层 ​

传输层 SSL Pinning / 证书校验
   ↓
存储层 flutter_secure_storage / Keystore / Keychain
   ↓
代码层 混淆 + 资源裁剪(Android R8 / iOS 发布)
   ↓
运行时 root/越狱检测、反调试、防抓包

二、传输层:SSL Pinning ​

防止中间人抓包篡改。Dio 侧可在拦截器做证书校验:

dart
// 伪代码:Dio 证书校验(真实实现要把 CA/公钥放到 assets 或原生层)
final dio = Dio(BaseOptions(baseUrl: baseUrl));
// 校验服务端证书是否匹配固定公钥

实现层选择:

方案位置优点注意
原生层证书锁定Android/iOS 原生最可靠,抓包也难绕过证书轮换要发版
Dio 拦截器校验Dart 层灵活、跨端统一反编译可绕过,仅防"普通中间人"
混合(原生 + Dart 兜底)双端纵深维护成本高

经验:证书/公钥要有轮换机制(备份公钥 + 版本控制),否则证书过期就是线上事故。


三、存储层:密钥与敏感数据 ​

不要用 SharedPreferences 存密钥/token:

数据正确存储原因
用户 tokenflutter_secure_storage(Keychain/Keystore)加密 + 系统级保护
API 密钥原生层(Android BuildConfig/原生 Secret)不进 Dart 源码
用户配置SharedPreferences非敏感,可明文
设备标识匿名化 ID,不落敏感关联隐私合规(见 38 篇)
dart
// 敏感 token 走安全存储
const storage = FlutterSecureStorage();
await storage.write(key: 'access_token', value: token);

四、代码层:混淆与加固 ​

4.1 Android ​

  • 发布构建开 minifyEnabled(R8 混淆 + 裁剪);
  • 商业加固(如腾讯乐固/梆梆/爱加密)做二次加固;
  • 资源裁剪降低逆向面与体积。

4.2 iOS ​

  • 发布构建默认 LLVM 优化,App Store 做基本保护;
  • 商业加固可选(越狱检测等)。

注意:混淆会让崩溃堆栈难读,需配合 20 篇 的符号化还原流程。


五、运行时:root/越狱与反调试 ​

高价值业务(支付、企业凭据)才需要:

  • root/越狱检测:root_detector 等插件,检测到后提示并降级/拒绝敏感操作;
  • 防调试/防抓包:Debug.isDebugMode 检查 + 发布版关闭日志;
  • 注意:检测逻辑写在 Dart 里可被逆向定位,关键判定尽量下沉原生。

(与 24 篇 联动)

风险措施
WebView 打开不可信 URL白名单校验,禁止任意 file:// / javascript:
Deep Link 被伪造拉起校验 scheme/host + 参数签名
JS Bridge 任意调用只暴露白名单方法,校验来源

七、安全基线清单(项目落地) ​

  1. 必须:token 进安全存储、API 密钥不进 Dart、HTTPS + 证书校验;
  2. 建议:SSL Pinning(含轮换机制)、Android 混淆 + 加固、崩溃符号化;
  3. 按业务:root/越狱检测、反调试、WebView 白名单;
  4. 流程:上线前做一次渗透/逆向评估,安全测试进 CI。

动手练习 ​

  1. 用 flutter_secure_storage 重构"token 明文存 SharedPreferences"的旧逻辑;
  2. 给 Dio 加证书校验拦截器(含备份公钥轮换的注释);
  3. 画一张"App 安全纵深"清单,标出每条措施落在哪一层。

自检清单 ​

  • [ ] 能说出四层安全纵深(传输/存储/代码/运行时)
  • [ ] 知道 SSL Pinning 的实现位置与证书轮换
  • [ ] 知道密钥为什么不能进 Dart 源码
  • [ ] 知道混淆不是安全边界,只是加高逆向成本
  • [ ] 会处理 WebView / Deep Link 的常见风险

常见误区 ​

  • "混淆了就很安全":混淆可被还原,密钥放 Dart 照样被抠出来;
  • "token 存 SharedPreferences 方便":明文存储是重灾区,改安全存储;
  • "SSL Pinning 一劳永逸":证书会过期,没有轮换机制就是定时炸弹;
  • "检测写 Dart 就行":关键安全判定要下沉原生,Dart 层可被逆向定位。

相关文档 ​