diff --git a/lib/app/services/kr_device_info_service.dart b/lib/app/services/kr_device_info_service.dart index 50e6107..b51dd34 100644 --- a/lib/app/services/kr_device_info_service.dart +++ b/lib/app/services/kr_device_info_service.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter_udid/flutter_udid.dart'; +import 'package:flutter_keychain/flutter_keychain.dart'; import '../utils/kr_secure_storage.dart'; import '../utils/kr_log_util.dart'; import 'package:crypto/crypto.dart'; @@ -142,24 +143,39 @@ class KRDeviceInfoService { } } - /// iOS设备ID - 优先使用identifierForVendor,配合持久化存储 - /// iOS限制较严,无法获取IMEI等敏感信息 + /// iOS设备ID - 优先使用Keychain存储的UUID(卸载重装后不变) + /// iOS的identifierForVendor在所有同供应商应用卸载后会重置 + /// 使用flutter_keychain存储到iOS Keychain,保证即使卸载重装,设备ID也不会变化 Future _getIOSDeviceId() async { try { + const keychainKey = 'kr_ios_device_persistent_id'; + + // 1. 优先从iOS Keychain读取已存储的设备ID(卸载后依然存在) + String? storedId = await FlutterKeychain.get(key: keychainKey); + + if (storedId != null && storedId.isNotEmpty) { + if (kDebugMode) { + print('📱 iOS: 从Keychain读取已存储的设备ID'); + } + KRLogUtil.kr_i('📱 iOS: 使用Keychain中的持久化设备ID', tag: 'KRDeviceInfoService'); + return storedId; + } + + // 2. 如果Keychain中没有,生成新的设备ID final iosInfo = await _deviceInfo.iosInfo; - // 优先使用 flutter_udid + // 使用硬件级别的信息生成唯一标识(作为备用方案) String udid = await FlutterUdid.consistentUdid; - // 构建多因子字符串 + // 构建多因子字符串(不使用会变化的identifierForVendor作为主要因子) final factors = [ udid, - iosInfo.identifierForVendor ?? '', // Vendor标识 + iosInfo.utsname.machine, // 硬件机器类型(如"iPhone14,3") iosInfo.model, // 型号 iosInfo.systemName, // 系统名 - iosInfo.systemVersion, // 系统版本 - iosInfo.name, // 设备名(如"iPhone 14 Pro") - iosInfo.utsname.machine, // 机器类型 + // 移除: iosInfo.identifierForVendor - 因为它会在卸载后变化 + // 移除: iosInfo.name - 用户可以修改设备名 + // 移除: iosInfo.systemVersion - 系统升级会变化 ]; final combined = factors @@ -168,13 +184,17 @@ class KRDeviceInfoService { final bytes = utf8.encode(combined); final hash = sha256.convert(bytes); + final newDeviceId = hash.toString(); + + // 3. 保存到iOS Keychain(即使应用卸载也会保留) + await FlutterKeychain.put(key: keychainKey, value: newDeviceId); if (kDebugMode) { - print('📱 iOS多因子ID生成 - 因子数: ${factors.where((f) => f.isNotEmpty).length}'); + print('📱 iOS: 生成新设备ID并保存到Keychain - 因子数: ${factors.where((f) => f.isNotEmpty).length}'); } - KRLogUtil.kr_i('📱 iOS多因子ID - $hash', tag: 'KRDeviceInfoService'); + KRLogUtil.kr_i('📱 iOS: 生成并持久化新设备ID到Keychain', tag: 'KRDeviceInfoService'); - return hash.toString(); + return newDeviceId; } catch (e) { if (kDebugMode) { print('❌ iOS设备ID获取失败: $e');