hi-client/lib/app/utils/kr_secure_storage.dart

220 lines
7.4 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:io';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:crypto/crypto.dart';
import 'dart:convert';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import 'package:path_provider/path_provider.dart';
class KRSecureStorage {
// 创建一个单例实例
static final KRSecureStorage _instance = KRSecureStorage._internal();
factory KRSecureStorage() => _instance;
// 私有构造函数
KRSecureStorage._internal();
// 存储箱名称
static const String _boxName = 'kaer_secure_storage';
// 加密密钥
static const String _encryptionKey = 'kaer_secure_storage_key';
// 初始化 Hive
Future<void> kr_initHive() async {
try {
// 根据不同平台指定数据库路径
if (Platform.isMacOS || Platform.isWindows || Platform.isLinux) {
final baseDir = await getApplicationSupportDirectory();
KRLogUtil.kr_i('初始化 Hive路径: ${baseDir.path}', tag: 'SecureStorage');
// 确保目录存在
if (!baseDir.existsSync()) {
await baseDir.create(recursive: true);
KRLogUtil.kr_i('已创建 Hive 目录: ${baseDir.path}', tag: 'SecureStorage');
}
await Hive.initFlutter(baseDir.path);
} else {
// Android 和 iOS 使用默认路径
await Hive.initFlutter();
}
// 使用加密适配器
final key = HiveAesCipher(_generateKey());
await Hive.openBox(_boxName, encryptionCipher: key);
KRLogUtil.kr_i('Hive 初始化成功', tag: 'SecureStorage');
} catch (e, stackTrace) {
KRLogUtil.kr_e('初始化 Hive 失败: $e', tag: 'SecureStorage');
KRLogUtil.kr_e('错误类型: ${e.runtimeType}', tag: 'SecureStorage');
KRLogUtil.kr_e('错误堆栈: $stackTrace', tag: 'SecureStorage');
// 对于 Windows 和 Linux如果初始化失败尝试删除旧文件并重试
if (Platform.isWindows || Platform.isLinux) {
try {
KRLogUtil.kr_i('尝试清理并重新初始化 Hive', tag: 'SecureStorage');
final baseDir = await getApplicationSupportDirectory();
final hiveDir = Directory(baseDir.path);
// 查找并删除相关的 Hive 文件
if (hiveDir.existsSync()) {
final files = hiveDir.listSync();
for (var entity in files) {
if (entity is File) {
final fileName = entity.path.split(Platform.pathSeparator).last;
// 删除 Hive 数据库文件(通常是 .hive 或 .lock 文件)
if (fileName.startsWith(_boxName) ||
fileName.endsWith('.hive') ||
fileName.endsWith('.lock')) {
try {
await entity.delete();
KRLogUtil.kr_i('已删除文件: $fileName', tag: 'SecureStorage');
} catch (deleteError) {
KRLogUtil.kr_e('删除文件失败: $deleteError', tag: 'SecureStorage');
}
}
}
}
}
// 重新初始化
await Hive.initFlutter(baseDir.path);
final key = HiveAesCipher(_generateKey());
await Hive.openBox(_boxName, encryptionCipher: key);
KRLogUtil.kr_i('Hive 重新初始化成功', tag: 'SecureStorage');
} catch (retryError, retryStack) {
KRLogUtil.kr_e('重新初始化 Hive 仍然失败: $retryError', tag: 'SecureStorage');
KRLogUtil.kr_e('重试堆栈: $retryStack', tag: 'SecureStorage');
rethrow;
}
} else {
rethrow;
}
}
}
// 生成加密密钥
List<int> _generateKey() {
final key = utf8.encode(_encryptionKey);
final hash = sha256.convert(key);
return hash.bytes;
}
// 🔧 修复:确保 box 始终打开
Future<Box<dynamic>> _ensureBoxOpen() async {
if (!Hive.isBoxOpen(_boxName)) {
KRLogUtil.kr_w('⚠️ Box 未打开,重新打开: $_boxName', tag: 'SecureStorage');
final key = HiveAesCipher(_generateKey());
await Hive.openBox(_boxName, encryptionCipher: key);
KRLogUtil.kr_i('✅ Box 已重新打开', tag: 'SecureStorage');
}
return Hive.box(_boxName);
}
// 存储数据
Future<void> kr_saveData({required String key, required String value}) async {
try {
final box = await _ensureBoxOpen();
await box.put(key, value);
// 🔧 关键修复:强制将数据立即写入磁盘,确保持久化
// 不调用 flush() 时,数据只在内存缓冲区中,应用关闭后会丢失!
await box.flush();
print('💾 [SecureStorage] 数据已保存并刷新到磁盘: $key');
KRLogUtil.kr_i('✅ 数据已保存: $key', tag: 'SecureStorage');
} catch (e) {
print('❌ [SecureStorage] 存储数据失败: $e');
KRLogUtil.kr_e('❌ 存储数据失败: $e', tag: 'SecureStorage');
rethrow; // 重新抛出异常,让调用者知道保存失败
}
}
// 读取数据
Future<String?> kr_readData({required String key}) async {
try {
final box = await _ensureBoxOpen();
final value = box.get(key) as String?;
KRLogUtil.kr_i('📖 读取数据: $key = ${value != null ? "存在" : "null"}', tag: 'SecureStorage');
return value;
} catch (e) {
KRLogUtil.kr_e('❌ 读取数据失败: $e', tag: 'SecureStorage');
return null;
}
}
// 删除数据
Future<void> kr_deleteData({required String key}) async {
try {
final box = await _ensureBoxOpen();
await box.delete(key);
KRLogUtil.kr_i('🗑️ 数据已删除: $key', tag: 'SecureStorage');
} catch (e) {
KRLogUtil.kr_e('❌ 删除数据失败: $e', tag: 'SecureStorage');
}
}
// 清除所有数据
Future<void> kr_clearAllData() async {
try {
final box = await _ensureBoxOpen();
await box.clear();
KRLogUtil.kr_i('🧹 所有数据已清除', tag: 'SecureStorage');
} catch (e) {
KRLogUtil.kr_e('❌ 清除数据失败: $e', tag: 'SecureStorage');
}
}
// 检查键是否存在
Future<bool> kr_hasKey({required String key}) async {
try {
final box = await _ensureBoxOpen();
return box.containsKey(key);
} catch (e) {
KRLogUtil.kr_e('❌ 检查键失败: $e', tag: 'SecureStorage');
return false;
}
}
// 保存布尔值
Future<void> kr_saveBool({required String key, required bool value}) async {
try {
final box = await _ensureBoxOpen();
await box.put(key, value);
} catch (e) {
KRLogUtil.kr_e('❌ 存储布尔值失败: $e', tag: 'SecureStorage');
}
}
// 获取布尔值
Future<bool?> kr_getBool({required String key}) async {
try {
final box = await _ensureBoxOpen();
return box.get(key) as bool?;
} catch (e) {
KRLogUtil.kr_e('❌ 读取布尔值失败: $e', tag: 'SecureStorage');
return null;
}
}
// 保存整数
Future<void> kr_saveInt({required String key, required int value}) async {
try {
final box = await _ensureBoxOpen();
await box.put(key, value);
} catch (e) {
KRLogUtil.kr_e('❌ 存储整数失败: $e', tag: 'SecureStorage');
}
}
// 获取整数
Future<int?> kr_getInt({required String key}) async {
try {
final box = await _ensureBoxOpen();
return box.get(key) as int?;
} catch (e) {
KRLogUtil.kr_e('❌ 读取整数失败: $e', tag: 'SecureStorage');
return null;
}
}
}