Files
life-echo/skills/auth-login-register.md
iammm0 6526c08c3a docs: 新增技能文档
- 新增Skills.md技能说明
- 新增skills/技能文档目录

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-03 11:30:12 +08:00

3.0 KiB
Raw Blame History

Skill登录与注册机制

与具体业务无关的认证设计:服务端 API 与客户端 Android 的登录、注册、令牌与鉴权约定。


服务端API

认证方式

  • 访问令牌Access TokenJWT用于接口鉴权默认有效期 2 小时(ACCESS_TOKEN_EXPIRE_MINUTES)。
  • 刷新令牌Refresh Token:随机字符串,存库,默认 30 天有效;用于在访问令牌过期后换取新访问令牌。

密码

  • 使用 bcrypt 哈希存储,不存明文。
  • 注册/登录时由 auth_service.hash_password / verify_password 处理。

登录/注册入口

  • 手机号 + 密码:POST /api/auth/loginPOST /api/auth/register
  • 手机号 + 短信验证码:POST /api/auth/login/sms(未注册则自动注册,需提供昵称)。
  • 所有入口均要求请求体中 agreed_to_terms == true,否则 400。

令牌刷新

  • POST /api/auth/refreshBody: { "refresh_token": "..." }
  • 校验:存在、未撤销、未过期、对应用户存在;通过后返回新的 access_tokenrefresh_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 PreferencesTokenPreferences)存 access_tokenrefresh_tokenuser_id
  • 通过单例 TokenManager 读写;提供 initialize(context)saveTokensgetAccessToken/getRefreshToken(含 suspend 与 sync 版本)、clearTokens

登录状态

  • TokenManager 维护 isLoggedIn(有有效 access_token 即为 true并提供 rememberIsLoggedIn() 供 Compose 使用。
  • 登出或刷新失败时调用 clearTokens()notifyTokenRefreshFailed(),由回调统一处理(如清栈并跳转登录页)。

请求头与刷新

  • 使用 AuthInterceptorKtor 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 } },保证回到登录且无法返回。