startup-plan/技术设计/ios-projects/已完成/[已完成]-登录集成.md

173 lines
4.3 KiB
Markdown
Raw Normal View History

# iOS 登录流程 —— iOS 端集成
---
## 一、iOS 需要的核心组件
```
AuthService ← 调后端登录接口
UserService ← 用户信息管理
TokenStore ← token 存储协议
KeychainTokenStore ← 基于 Keychain 的安全存储实现
AppSession ← 管理当前登录态
```
---
## 二、数据存储策略
| 数据 | 存储位置 | 生命周期 | 原因 |
|------|---------|---------|------|
| `accessToken` | 内存 | App 运行期间 | 短期使用,不需要持久化 |
| `refreshToken` | Keychain | 长期持久化 | 敏感凭证,需安全存储,卸载后也保留 |
| `user` | AppSession / UserStore | App 运行期间 | 用户展示信息 |
---
## 三、App 启动流程
```
App 启动
→ AppSession.checkSession()
→ 从 Keychain 读取 refreshToken
→ 如果没有 refreshToken
→ 进入登录页
→ 如果有 refreshToken
→ 调用 POST /api/auth/refresh
→ 成功
→ 存储新的 accessToken + refreshToken
→ 调用 GET /api/users/me
→ 存储 user 信息
→ 进入主界面
→ 失败
→ 清空 Keychain + 内存 token
→ 进入登录页
```
---
## 四、登录流程
### 开发登录dev-login
```
用户在登录页输入邮箱/昵称
→ AuthService.devLogin(email, nickname)
→ POST /api/auth/dev-login
→ 后端返回 { accessToken, refreshToken, user }
→ refreshToken 存 Keychain
→ accessToken 放内存
→ user 放 AppSession
→ 进入主界面
```
### Apple 登录
```
用户点击 Sign in with Apple
→ iOS 系统弹出 Apple 授权界面
→ 用户授权成功
→ 拿到 identityToken + authorizationCode 等
→ AuthService.appleLogin(identityToken, ...)
→ POST /api/auth/apple
→ 后端验证 Apple token返回 { accessToken, refreshToken, user }
→ refreshToken 存 Keychain
→ accessToken 放内存
→ user 放 AppSession
→ 进入主界面
```
---
## 五、接口请求拦截
所有需要登录的接口都必须携带:
```http
Authorization: Bearer {accessToken}
```
### HTTP Client 封装建议
```
所有请求自动注入 Authorization Header
→ 从 AuthService 获取当前 accessToken
→ 自动添加到请求头
```
### 401 自动处理
```
接口返回 401
→ 调用 POST /api/auth/refresh
→ 成功
→ 更新 accessToken
→ 自动重试原请求
→ 失败
→ 清空 Keychain + 内存数据
→ 跳转登录页
```
**重要**:重试原请求时注意避免无限循环,设置最多重试 1 次。
---
## 六、退出登录
```
用户点击退出登录
→ AuthService.logout()
→ POST /api/auth/logout
Body: { refreshToken: 从 Keychain 取的 refreshToken }
Header: Authorization: Bearer accessToken
→ 后端标记 refreshToken revoked
→ iOS 端:
→ 清除 Keychain 中的 refreshToken
→ 清除内存中的 accessToken
→ 清除 AppSession 中的 user
→ 跳转登录页
```
---
## 七、Token 存储对比UserDefaults vs Keychain
| | UserDefaults | Keychain |
|------|------------|----------|
| 安全性 | 低(明文存储) | 高(系统级加密) |
| 应用卸载后 | 数据被清除 | 可选保留(推荐保留) |
| 备份 | 包含在 iTunes/iCloud 备份中 | 仅加密备份 |
| 适用数据 | 非敏感偏好设置 | 密码、Token 等敏感凭据 |
**结论refreshToken 一定要用 Keychain 存储。**
---
## 八、Session 状态机
```
App 启动
┌─────────────────┐
│ 检查 Keychain │
│ 有 refreshToken? │
└───────┬─────────┘
┌───────┴───────┐
│ 有 │ 无
▼ ▼
┌─────────┐ ┌──────────┐
│ 调 refresh │ │ 进入登录页 │
│ 接口 │ └──────────┘
└─────┬─────┘
┌────┴────┐
│ 成功 │ 失败
▼ ▼
┌────────┐ ┌──────────┐
│ 调 /me │ │ 清空数据 │
│ 进主页 │ │ 进登录页 │
└────────┘ └──────────┘
```