登录与会话
纯前端商业版提供完整的前端认证链路,但不绑定特定后端语言或身份平台。所有认证 HTTP 接口统一放在 src/api/auth.ts,请求层负责附加 Token,路由守卫负责恢复用户和权限,客户后端负责真正的身份校验与会话安全。
认证链路
核心文件:
src/api/auth.ts
src/services/auth.ts # 现有认证流程封装,不存放接口定义
src/utils/http/index.ts
src/store/modules/user.ts
src/router/guards/beforeEach.ts依赖方向如下:
登录页 / 路由守卫
-> 现有认证流程封装
-> src/api/auth.ts
-> 统一 HTTP 请求层
-> 客户后端页面不应直接操作 LocalStorage,也不应自行拼接 Authorization 请求头。
接口目录规则
登录、退出、当前用户、验证码和 Refresh Token 等请求函数全部放在 src/api/auth.ts。src/services/auth.ts 只能调用这些 API 并组合认证流程,不能定义新的请求 URL。
登录流程
提交账号密码
-> POST /api/v1/auth/signin
-> 校验 accessToken 为非空字符串
-> userStore 保存 Access Token
-> 跳转目标路由
-> 路由守卫获取当前用户
-> 初始化角色、按钮权限、菜单和动态路由登录接口请求:
{
"username": "Super",
"password": "123456"
}响应 data 至少包含:
{
"accessToken": "your-access-token"
}当前认证流程会在调用 src/api/auth.ts 后拒绝空字符串或格式错误的 Token,避免无效登录态进入后续路由流程。
当前用户接口
登录后和页面刷新时,系统都会调用:
GET /api/v1/user/info
Authorization: Bearer <accessToken>核心响应:
{
"id": 1,
"username": "Super",
"email": "super@example.com",
"roles": ["R_SUPER"],
"buttons": ["*"]
}前端会校验:
id必须是有限数字。username必须是非空字符串。email必须是字符串。roles、buttons必须是非空字符串组成的数组。buttons使用*时不能再混合其他权限码。
严格校验可以让后端契约错误尽早暴露,避免畸形权限数据造成错误展示或意外放行。
页面刷新与会话恢复
用户 Store 持久化 Access Token,但不长期持久化完整用户资料和权限:
刷新页面
-> Pinia 恢复 Access Token
-> 恢复本地 Access Token
-> 路由守卫请求当前用户
-> 使用最新角色和按钮权限重建菜单这样处理有两个直接收益:
- 用户权限在服务端变化后,刷新即可获得最新结果。
- 浏览器不会长期使用一份过期的用户和权限快照。
当前只实现 Access Token
项目没有内置 Refresh Token、静默续期或并发刷新队列。Access Token 过期后,由 401 流程清理登录态并返回登录页。
请求携带 Token
统一请求层从 userStore 读取 Token,并添加:
Authorization: Bearer <accessToken>认证之外的业务 API 不需要重复编写 Token 逻辑:
import request from '@/utils/http'
export function fetchProfile() {
return request.get<Api.Account.Profile>({
url: '/api/v1/account/profile'
})
}如果客户后端使用 Cookie 会话,应统一调整请求层和 VITE_WITH_CREDENTIALS,而不是在个别 API 上混用两套认证方式。
401 与退出登录
请求层收到业务码或 HTTP 状态 401 时,会触发统一登出:
401
-> 清理 Access Token 和用户信息
-> 清理动态路由与菜单状态
-> 清理跨账号敏感偏好
-> 跳转登录页并携带原目标地址用户主动退出时会调用:
POST /api/v1/auth/logout无论后端退出请求是否成功,前端最终都应清理本地认证状态。后端则负责撤销服务端会话或使令牌失效。
权限与认证的边界
登录成功只证明用户获得了一个可用于请求的令牌,不代表用户拥有所有页面和操作权限:
roles决定本地菜单过滤和角色指令。buttons决定按钮、操作项和前端交互展示。- 菜单树决定当前用户可见的业务入口。
- 后端必须继续校验每个数据接口和写操作。
前端权限用于改善体验,不能作为数据安全边界。完整模型见路由与权限。
扩展 Refresh Token
客户后端需要双令牌协议时,建议把扩展限制在以下位置:
- 在认证 API 中增加刷新接口。
- 在用户 Store 中统一保存和清理双令牌。
- 在 HTTP 层实现单实例刷新任务和失败请求队列。
- 刷新失败时进入现有统一登出流程。
- 避免多个并发 401 同时发起刷新请求。
不要让页面组件感知 Refresh Token,也不要在每个 API 文件中重复刷新逻辑。
项目未内置的协议
当前源码没有内置以下能力:
- RSA 密码加密
- 请求签名、Nonce、时间戳校验
- 图形验证码协议
- OAuth/OIDC 跳转流程
- Refresh Token 自动续期
这些能力与客户后端、安全策略和身份平台高度相关,应该在明确协议后接入。生产环境至少必须使用 HTTPS,不能把前端加密当作传输安全的替代品。
联调检查
- 登录接口返回非空
accessToken。 - 当前用户字段通过前端校验。
- 刷新受保护页面后能恢复菜单。
- 无效 Token 返回 401,而不是返回空用户。
- 主动退出后旧 Token 无法继续访问后端接口。
- 不同账号切换时不会继承上一个账号的敏感状态。
