3.0 KiB
3.0 KiB
Skill:登录与注册机制
与具体业务无关的认证设计:服务端 API 与客户端 Android 的登录、注册、令牌与鉴权约定。
服务端(API)
认证方式
- 访问令牌(Access Token):JWT,用于接口鉴权,默认有效期 2 小时(
ACCESS_TOKEN_EXPIRE_MINUTES)。 - 刷新令牌(Refresh Token):随机字符串,存库,默认 30 天有效;用于在访问令牌过期后换取新访问令牌。
密码
- 使用 bcrypt 哈希存储,不存明文。
- 注册/登录时由
auth_service.hash_password/verify_password处理。
登录/注册入口
- 手机号 + 密码:
POST /api/auth/login、POST /api/auth/register。 - 手机号 + 短信验证码:
POST /api/auth/login/sms(未注册则自动注册,需提供昵称)。 - 所有入口均要求请求体中
agreed_to_terms == true,否则 400。
令牌刷新
POST /api/auth/refresh,Body:{ "refresh_token": "..." }。- 校验:存在、未撤销、未过期、对应用户存在;通过后返回新的
access_token,refresh_token原样返回(不轮换)。
鉴权依赖
- 需要登录的接口:
Depends(get_current_user),从Authorization: Bearer <access_token>解析 JWT,校验type == "access"并加载用户。 - 可选登录:
Depends(get_optional_user),无 token 或无效时返回None。
路由与安全
- 认证相关路由统一前缀:
/api/auth(如 login、register、refresh、logout 等)。 - OAuth2 约定:
OAuth2PasswordBearer(tokenUrl="/api/auth/login"),仅用于声明从哪里取 token,实际登录仍用上述接口。
客户端(Android)
令牌存储
- 使用 DataStore Preferences(
TokenPreferences)存access_token、refresh_token、user_id。 - 通过单例 TokenManager 读写;提供
initialize(context)、saveTokens、getAccessToken/getRefreshToken(含 suspend 与 sync 版本)、clearTokens。
登录状态
- TokenManager 维护
isLoggedIn(有有效 access_token 即为 true),并提供rememberIsLoggedIn()供 Compose 使用。 - 登出或刷新失败时调用
clearTokens()并notifyTokenRefreshFailed(),由回调统一处理(如清栈并跳转登录页)。
请求头与刷新
- 使用 AuthInterceptor(Ktor Client 插件):请求前自动附加
Authorization: Bearer <access_token>。 - 收到 401 时:用当前 refresh_token 调
AuthService.refreshToken();成功则写回新 token,失败则clearTokens()+notifyTokenRefreshFailed(),由 App 层跳转登录。
登录成功/登出与导航
- 登录成功:由各登录入口回调
onLoginSuccess,主流程将isLoggedIn = true并导航到主界面(如会话列表),并popUpTo(Login)清掉登录页。 - 登出或刷新失败:
onLogout/ TokenManager 回调中执行navController.navigate(Screen.Login.route) { popUpTo(0) { inclusive = true } },保证回到登录且无法返回。