You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中存储.ts/mp4视频并限制仅应用可访问的实现方案

Flutter 离线加密视频存储方案(防止外部应用访问)

一、应用私有目录存储(基础防护)

  • Android 和 iOS 都提供应用专属私有存储目录,默认仅当前应用可访问,系统相册及其他外部应用无法直接读取:
    • Android:通过path_provider包的getApplicationDocumentsDirectory()获取,对应内部存储的/data/data/[包名]/files/,无需额外权限,卸载应用时会自动删除目录内容。
    • iOS:同样使用getApplicationDocumentsDirectory(),对应沙盒内的Documents目录;若不想被iTunes备份,可搭配getTemporaryDirectory()(临时文件,系统可能自动清理),或给文件设置NSURLIsExcludedFromBackupKey属性。
  • 注意:该方式仅为基础防护,root后的Android设备或越狱iOS仍可访问目录,需配合加密手段提升安全性。

二、视频文件加密(核心防护)

1. 对称加密(推荐,性能适配视频场景)

采用AES-256-GCM(或CBC)算法加密视频文件,存储加密后的文件,播放时流式解密读取(避免一次性解密占用大量内存):

  • 密钥存储:用flutter_secure_storage包将密钥存于Android Keystore或iOS Keychain,禁止硬编码密钥。
  • 加密写入:下载视频时可边下载边加密写入本地,或下载完成后批量加密,示例代码片段:
    // 简化加密逻辑
    final key = await _secureStorage.read(key: 'video_enc_key');
    final iv = Random.secure().bytes(12); // GCM模式推荐12字节IV
    final encrypter = Encrypter(AES(Key.fromUtf8(key), mode: AESMode.gcm));
    
    // 流式加密写入文件
    final outputFile = File('${dir.path}/xxx.dat');
    final outputStream = outputFile.openWrite();
    final inputStream = httpClient.send(request).asStream();
    
    await for (var chunk in inputStream) {
      final encryptedChunk = encrypter.encryptBytes(chunk.bytes, iv: IV(iv)).bytes;
      outputStream.add(encryptedChunk);
    }
    await outputStream.close();
    // 保存IV(解密必需),可与加密文件同目录存储
    await File('${dir.path}/xxx.iv').writeAsBytes(iv);
    
  • 解密播放:需实现自定义数据源,流式解密后提供给播放器(如video_player或chewie),示例代码片段:
    // 简化解密流式读取
    final encryptedFile = File('${dir.path}/xxx.dat');
    final iv = await File('${dir.path}/xxx.iv').readAsBytes();
    final key = await _secureStorage.read(key: 'video_enc_key');
    final encrypter = Encrypter(AES(Key.fromUtf8(key), mode: AESMode.gcm));
    
    final inputStream = encryptedFile.openRead();
    final decryptedStream = inputStream.transform(StreamTransformer.fromHandlers(
      handleData: (chunk, sink) {
        final decryptedChunk = encrypter.decryptBytes(Encrypted(chunk), iv: IV(iv));
        sink.add(decryptedChunk);
      },
    ));
    
    // 将解密流转换为播放器可识别的数据源,如临时文件或内存缓存
    

2. 轻量加密替代(性能敏感场景)

若全文件加密性能压力较大,可仅加密视频关键帧或文件头,让外部应用无法正常解析播放,安全性略低但性能更优。

三、文件名与目录混淆

  • 用随机字符串(如Uuid().v4()生成)作为文件名和目录名,避免使用原视频文件名或.mp4/.ts后缀,改用自定义后缀(如.dat),降低被系统相册扫描识别的概率。

四、额外防护措施

  • Android:在AndroidManifest.xml中设置android:allowBackup="false",防止应用备份被导出获取文件;禁止使用外部存储(External Storage),避免文件被公开访问。
  • iOS:开启Xcode Capabilities中的Data Protection,设备锁定时自动加密存储文件;播放时可通过插件(如flutter_windowmanager)禁止截图录屏。
  • 播放环节:Android设置FLAG_SECURE,iOS配置AVPlayerViewController相关属性,防止用户通过截图录屏传播内容。

内容的提问来源于stack exchange,提问作者Hkm Sadek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 08:12:44