背景
- 项目已经是端到端加密:
- 客户端在本地用 AES-256-GCM 加密后,才上传到 S3。
- S3 只看到密文,传输层即使被窃听也无法解开。
- 这种场景下,TLS 的价值更多是“防止元数据泄露”和“防劫持”,但在可信局域网或自建环境中,优先级可以适当降低。
- 我这边的诉求:
- 默认尽量追求传输简单和性能优先。
- 不希望一装就默认开 TLS,尤其是在 MinIO 这种常见的非 TLS 配置下。
- 另外,设置中提供了“清除所有应用数据”操作,直觉上应该把包括 S3 TLS 开关在内的所有偏好一起恢复为默认。
本次调整围绕两个问题:
- S3
useSsl的默认值与加载逻辑。 - “清除所有应用数据”是否真的把 TLS 开关恢复为默认关闭。
客户端 S3 TLS 默认值
偏好加载逻辑
- 所有偏好在
AppState._loadPreferences中加载:- 位置:
client/lib/core/state/app_state.dart:133-151 - 与 S3 相关的字段:
_s3Endpoint = prefs.getString('s3_endpoint');_s3AccessKey = prefs.getString('s3_access_key');_s3SecretKey = prefs.getString('s3_secret_key');_s3Bucket = prefs.getString('s3_bucket');_s3UseSsl = prefs.getBool('s3_use_ssl') ?? false;
- 位置:
- 关键在最后一行:
- 如果本地偏好里还没有
s3_use_ssl这个 key,则使用false作为默认值。 - 这保证了“新装应用”或者“从未修改过 TLS 设置”的情况下,TLS 是关闭的。
- 如果本地偏好里还没有
对外暴露与修改
- 对外 getter:
bool get s3UseSsl => _s3UseSsl;,client/lib/core/state/app_state.dart:221-243 - 修改方法:
Future<void> setS3UseSsl(bool value),client/lib/core/state/app_state.dart:339-345- 直接更新内存中的
_s3UseSsl。 - 将值写入
SharedPreferences的s3_use_ssl。 - 触发
notifyListeners()。
- 直接更新内存中的
- 设置页中的 UI 开关:
- 位于 S3 配置弹窗的
SwitchListTile:client/lib/ui/settings_page.dart:169-243
- 初始值取自
appState.s3UseSsl。 - 副标题文案明确:“默认关闭,以提升传输速度”。
- 位于 S3 配置弹窗的
与后端默认值的对应
- Go 核心的默认配置同样是
UseSSL: false:core/internal/config/config.go:27-46DefaultConfig().S3.UseSSL被设置为false。
- 这意味着:
- 如果客户端不显式要求启用 TLS,后端默认也是以非 TLS 端点工作(通常是 MinIO 的 http://host:9000)。
- 前后端在“默认关闭 TLS”这个点上保持一致。
清除 App 数据后的 TLS 行为
清除入口与调用链
- 设置页面的“清除所有应用数据”:
- UI 入口:
client/lib/ui/settings_page.dart:361-409 - 点击后弹出二次确认,对话内容明确说明只清除本地数据,不动服务器文件。
- 确认后执行:
await appState.clearAllAppData();await ThumbnailCacheManager().clearAllThumbnails();- 重置本地一些 UI 状态,并重启到
HomePage。
- UI 入口:
clearAllAppData 的具体行为
- 方法定义:
client/lib/core/state/app_state.dart:1400-1444 - 做的事情包括:
- 清空
SharedPreferences:await prefs.clear(); - 清除本地数据库中的所有文件元数据、下载任务、传输记录与 app 配置。
- 重置内存中的状态为“初始值”,例如:
_isInitialized = false;_isUnlocked = false;_currentPath = '/';_files = [];_uploadConcurrency = 3;_downloadConcurrency = 3;_sortField = FileSortField.name;_sortDirection = FileSortDirection.asc;_s3Endpoint = null;_s3AccessKey = null;_s3SecretKey = null;_s3Bucket = null;_s3UseSsl = false;_appPinCode = null;_appPinRequired = false;_themeMode = ThemeMode.system;
- 清空 API 的认证 token:
api.clearAuthToken();
- 清空
- 注意
_s3UseSsl = false;这一行:- 即使之前手动打开了 TLS 开关,
clearAllAppData之后也会把它显式改回false。 - 再加上
SharedPreferences全量clear(),下次启动_loadPreferences时,也会重新走默认的?? false。
- 即使之前手动打开了 TLS 开关,
曾经遇到的困惑
- 开发过程中曾出现过一种错觉:
- 点击“清除应用数据”后,重新打开设置页,发现 TLS 开关“看起来还是开着”。
- 实际原因往往是:
- UI 没有及时刷新,或者旧的
AppState实例仍然在内存里。 - 没有完整走完“清除 → 重建 AppState → 重新加载偏好”的链路。
- UI 没有及时刷新,或者旧的
- 经检查
clearAllAppData代码和实际运行行为后确认:- 从持久化角度看,TLS 状态已经被重置为默认关闭。
- 改完后,只要重新启动应用或完整走一遍
HomePage构建流程,界面上的开关就会与真实状态对齐。
总结
- 默认行为:
- 客户端和后端的 S3 TLS 默认值都是
false。 - 新安装或从未配置过的情况下,都是以非 TLS 方式访问 S3。
- 客户端和后端的 S3 TLS 默认值都是
- 配置行为:
- 可以在 S3 配置弹窗中显式打开“使用 HTTPS”。
- 该选项会写入本地偏好,并通过
AppState的 getter 驱动 UI 展示。
- 清理行为:
- “清除所有应用数据”会:
- 清空所有偏好(包括 S3 TLS 设置)。
- 把内存中的
_s3UseSsl重置为false。
- 只要重新进入应用主流程,TLS 开关会正确回到“关闭”状态。
- “清除所有应用数据”会:
- 整体上一致遵循了一个简单的原则:
- 端到端加密已经保证数据安全,TLS 默认为关闭,有需要时手动开启。