client_framework/docs/device_id_and_sign.md
2026-04-17 22:45:45 +08:00

76 lines
2.9 KiB
Markdown
Raw Permalink 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.

# 设备 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. 兜底设备 IDSharedPreferences
当 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` 绑定,不在此规范范围内。)
---