76 lines
2.9 KiB
Markdown
76 lines
2.9 KiB
Markdown
# 设备 ID 与 fast_login 签名(宿主参考实现)
|
||
|
||
本文档描述 **FunyMee** 等换皮应用在实现 [`AuthServiceCallbacks`](../lib/src/services/auth_service.dart) 时采用的 **`getDeviceId`** 与 **`computeSign`** 规则,与 **app_client** 行为对齐,便于其它宿主复制或迁移到框架内默认实现。
|
||
|
||
框架本身仍通过接口要求宿主提供上述方法;本文档**不是**框架 API 说明,而是**可复现的实现规范**。
|
||
|
||
---
|
||
|
||
## 1. 依赖(宿主 `pubspec.yaml`)
|
||
|
||
| 用途 | 包名 |
|
||
|------|------|
|
||
| Android:`Settings.Secure.ANDROID_ID` | [`android_id`](https://pub.dev/packages/android_id) |
|
||
| iOS:厂商级设备标识 | [`device_info_plus`](https://pub.dev/packages/device_info_plus) |
|
||
| 兜底 ID 持久化 | [`shared_preferences`](https://pub.dev/packages/shared_preferences) |
|
||
| 签名 MD5 | [`crypto`](https://pub.dev/packages/crypto)(`md5`) |
|
||
|
||
---
|
||
|
||
## 2. `getDeviceId()` 行为
|
||
|
||
按 [`defaultTargetPlatform`](https://api.flutter.dev/flutter/foundation/defaultTargetPlatform.html) 分支:
|
||
|
||
### 2.1 Android
|
||
|
||
- 使用 **`android_id` 包**的 `AndroidId().getId()`,对应系统 **`Settings.Secure.ANDROID_ID`**。
|
||
- 若返回值非空,直接作为 `deviceId`。
|
||
- **不要**用 `device_info_plus` 的 `AndroidDeviceInfo.id` 当作设备 ID:该字段通常为 **ROM 构建号(Build ID)**,与业务侧期望的 ANDROID_ID 不一致。
|
||
|
||
### 2.2 iOS
|
||
|
||
- 使用 `DeviceInfoPlugin().iosInfo`,取 **`identifierForVendor`**(IDFV)。
|
||
- 若非空,直接作为 `deviceId`。
|
||
|
||
### 2.3 其它平台或读取失败
|
||
|
||
- 使用下文 **§3 兜底 ID**,保证同一安装会话内稳定、可持久化。
|
||
|
||
---
|
||
|
||
## 3. 兜底设备 ID(SharedPreferences)
|
||
|
||
当 Android/iOS 无法取得有效 ID,或目标平台非 Android/iOS 时:
|
||
|
||
1. 读取键名:**`persisted_device_id`**(字符串)。
|
||
2. 若已有非空值,直接返回。
|
||
3. 否则生成新 ID:
|
||
- 使用加密安全随机数生成 **16 字节**;
|
||
- 经 **Base64URL** 编码后,**去掉末尾 `=` 填充**(与现有实现一致)。
|
||
4. 写入 SharedPreferences 后返回。
|
||
|
||
> 注意:不同应用若使用相同键名与存储作用域,行为一致;若宿主需隔离多环境,可自行加前缀或改用独立文件名。
|
||
|
||
---
|
||
|
||
## 4. `computeSign(deviceId)`
|
||
|
||
与后端 **`fast_login`** 约定一致:
|
||
|
||
- 对 **`deviceId` 的 UTF-8 字节**做 **MD5**;
|
||
- 结果为 **32 位十六进制字符串**,**大写**(例如 Dart:`md5.convert(utf8.encode(deviceId)).toString().toUpperCase()`)。
|
||
|
||
该签名对应代理层/V2 包装中的业务字段(如文档中的 `mandate` / `sign` 等,以实际字段映射为准)。
|
||
|
||
---
|
||
|
||
## 5. 参考代码位置(FunyMee)
|
||
|
||
实现类:**`AppAuthCallbacks`**,文件:
|
||
|
||
`FunyMee/lib/core/auth/auth_service.dart`
|
||
|
||
(仅 `getDeviceId`、`computeSign` 及 `_persistedFallbackDeviceId` 与本文档对应;其余如 `onLoginSuccess` 与宿主 `UserState` 绑定,不在此规范范围内。)
|
||
|
||
---
|