# 9.8 登录流程 :::tip 概述 登录页支持多表单形态(账号/手机/Qrcode),核心链路为:验证码获取 → 登录请求 → access_token 存储 → 跳转首页。前端读 `data.access_token`(下划线例外),守卫与 http 拦截器全程携带。 ::: ## 登录页结构(views/login/) ```text views/login/ ├── index.vue 登录页容器(多表单切换) ├── LoginForm.vue 账号密码表单(默认) ├── PhoneForm.vue 手机号表单形态 ├── QrcodeForm.vue 扫码表单形态 └── RegisterForm.vue 注册表单形态(后端 /api/register 路由未注册——当前不可用) ``` ## 核心登录链路(账号表单) ```text 1. 页面加载 → GET /api/captcha → {key, captcha(base64 图片)} 2. 用户填账号/密码/验证码 → Login action POST /api/login {username, password, code, key} (开发环境验证码可填 bypassCode 618618 免校验) 3. 成功响应: {data: {access_token, refresh_token, expires_in, token_type}} 前端读 data.access_token → storage.set(ACCESS_TOKEN) + store 4. 跳转首页(或 redirect 参数记录的来源路径) 5. 后续请求:http 拦截器从 storage 读 token 注入 Authorization 头 ``` ::: warning 字段名 登录响应是全系统唯一下划线命名:`data.access_token`(不是 accessToken)。读错字段是登录后仍跳登录页的最常见原因。 ::: ## token 生命周期(前端侧) ```text 写入:登录成功 / URL ?token= 直达(守卫识别写入) 读取:守卫校验 / http 拦截器注入 清除:登出(LogOut)/ 401 未认证 刷新:access 过期(401)→ refresh_token 走 /api/oauth2/token 轮换 (对接实现见 8.6 Token 使用说明) ``` ## 多表单形态说明 | 形态 | 说明 | |------|------| | LoginForm | 默认账号密码 + 验证码 | | PhoneForm | 手机号形态(界面演示;后端登录以账号/租户编码为准) | | QrcodeForm | 扫码形态(界面演示;对接需扫码通道) | | RegisterForm | 注册形态(后端 /api/register 白名单放行但路由未注册——启用需补后端实现) | 生产启用形态可在登录页配置裁剪。 ## 租户内登录 ```text 多租户同名场景:登录请求携带 tenantCode(租户编码) 后端先按 code 定位租户再按 username 过滤 不带:全局查找,同名时优先平台租户,仍歧义提示携带租户编码 登录表单如需租户输入框:加 tenantCode 字段随请求提交即可 ``` ## 排障 | 症状 | 原因 | |------|------| | 登录成功又跳回登录页 | 读错 access_token 字段;或 storage 写入失败(隐私模式) | | 验证码不显示 | 后端未启动 / /api/captcha 限流(认证入口 10/分钟) | | 登录报"验证码错误" | 每次 key 配套唯一验证码(一次性);用新 key 或 bypassCode | | 登录 429 | 触发 authLimit——等 1 分钟窗口过期 | | 登录报"演示环境" | 不应出现——登录在公开白名单放行;检查 demo 配置 | | 跳转丢 redirect | 守卫 redirect 参数未透传;检查白名单与 query 处理 |