Flutter中存储.ts/mp4视频并限制仅应用可访问的实现方案
Flutter 离线加密视频存储方案(防止外部应用访问)
一、应用私有目录存储(基础防护)
- Android 和 iOS 都提供应用专属私有存储目录,默认仅当前应用可访问,系统相册及其他外部应用无法直接读取:
- Android:通过
path_provider包的getApplicationDocumentsDirectory()获取,对应内部存储的/data/data/[包名]/files/,无需额外权限,卸载应用时会自动删除目录内容。 - iOS:同样使用
getApplicationDocumentsDirectory(),对应沙盒内的Documents目录;若不想被iTunes备份,可搭配getTemporaryDirectory()(临时文件,系统可能自动清理),或给文件设置NSURLIsExcludedFromBackupKey属性。
- Android:通过
- 注意:该方式仅为基础防护,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
相关产品推荐
相关产品推荐

