2026-06-30 14:46:52 +08:00
|
|
|
|
# 登录页面
|
|
|
|
|
|
|
|
|
|
|
|
<cite>
|
|
|
|
|
|
**本文档引用的文件**
|
|
|
|
|
|
- [frontend/src/views/login/index.vue](file://frontend/src/views/login/index.vue)
|
|
|
|
|
|
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js)
|
|
|
|
|
|
- [frontend/src/utils/auth.js](file://frontend/src/utils/auth.js)
|
|
|
|
|
|
- [frontend/src/utils/request.js](file://frontend/src/utils/request.js)
|
|
|
|
|
|
- [frontend/src/router/index.js](file://frontend/src/router/index.js)
|
|
|
|
|
|
- [frontend/src/utils/tabs.js](file://frontend/src/utils/tabs.js)
|
|
|
|
|
|
- [backend/src/routes/auth.js](file://backend/src/routes/auth.js)
|
|
|
|
|
|
- [backend/src/utils/jwt.js](file://backend/src/utils/jwt.js)
|
|
|
|
|
|
- [backend/src/middleware/auth.js](file://backend/src/middleware/auth.js)
|
|
|
|
|
|
- [backend/src/utils/password.js](file://backend/src/utils/password.js)
|
|
|
|
|
|
- [backend/src/utils/response.js](file://backend/src/utils/response.js)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css](file://frontend/src/styles/lux-theme.css)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
</cite>
|
|
|
|
|
|
|
2026-07-10 16:51:05 +08:00
|
|
|
|
## 更新摘要
|
|
|
|
|
|
**变更内容**
|
|
|
|
|
|
- 更新了登录按钮样式实现,从复杂渐变背景简化为纯色背景配合 backdrop-filter 模糊效果
|
|
|
|
|
|
- 优化了性能表现,同时保持了玻璃拟态美学设计
|
|
|
|
|
|
- 增强了按钮的视觉层次和交互反馈
|
|
|
|
|
|
|
2026-06-30 14:46:52 +08:00
|
|
|
|
## 目录
|
|
|
|
|
|
1. [简介](#简介)
|
|
|
|
|
|
2. [项目结构](#项目结构)
|
|
|
|
|
|
3. [核心组件](#核心组件)
|
|
|
|
|
|
4. [架构总览](#架构总览)
|
|
|
|
|
|
5. [详细组件分析](#详细组件分析)
|
|
|
|
|
|
6. [依赖关系分析](#依赖关系分析)
|
|
|
|
|
|
7. [性能考虑](#性能考虑)
|
|
|
|
|
|
8. [故障排除指南](#故障排除指南)
|
|
|
|
|
|
9. [结论](#结论)
|
|
|
|
|
|
|
|
|
|
|
|
## 简介
|
|
|
|
|
|
本文件面向登录页面的完整技术文档,涵盖前端登录表单设计、字段验证、提交处理与响应处理;后端认证机制、JWT 令牌生成与校验;登录状态持久化与路由守卫;安全措施(密码哈希、防暴力破解思路、会话管理);登录成功后的路由跳转、权限检查与用户信息初始化流程;错误处理、用户体验优化与移动端适配等实现细节。
|
|
|
|
|
|
|
|
|
|
|
|
## 项目结构
|
|
|
|
|
|
登录功能涉及前后端协作:前端负责表单渲染、输入校验、请求发送与状态持久化;后端负责用户鉴权、密码校验、JWT 签发与中间件保护。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph TB
|
|
|
|
|
|
subgraph "前端"
|
|
|
|
|
|
LoginView["登录视图<br/>frontend/src/views/login/index.vue"]
|
|
|
|
|
|
AuthAPI["认证 API<br/>frontend/src/api/auth.js"]
|
|
|
|
|
|
AuthUtil["认证工具<br/>frontend/src/utils/auth.js"]
|
|
|
|
|
|
RequestUtil["HTTP 请求封装<br/>frontend/src/utils/request.js"]
|
|
|
|
|
|
Router["路由守卫<br/>frontend/src/router/index.js"]
|
|
|
|
|
|
TabsUtil["标签页工具<br/>frontend/src/utils/tabs.js"]
|
2026-07-10 16:51:05 +08:00
|
|
|
|
Styles["主题样式<br/>frontend/src/styles/lux-theme.css"]
|
2026-06-30 14:46:52 +08:00
|
|
|
|
end
|
|
|
|
|
|
subgraph "后端"
|
|
|
|
|
|
AuthRoute["认证路由<br/>backend/src/routes/auth.js"]
|
|
|
|
|
|
JWTUtil["JWT 工具<br/>backend/src/utils/jwt.js"]
|
|
|
|
|
|
PasswordUtil["密码工具<br/>backend/src/utils/password.js"]
|
|
|
|
|
|
AuthMW["认证中间件<br/>backend/src/middleware/auth.js"]
|
|
|
|
|
|
RespUtil["响应封装<br/>backend/src/utils/response.js"]
|
|
|
|
|
|
end
|
|
|
|
|
|
LoginView --> AuthAPI
|
|
|
|
|
|
AuthAPI --> RequestUtil
|
|
|
|
|
|
RequestUtil --> AuthRoute
|
|
|
|
|
|
AuthRoute --> JWTUtil
|
|
|
|
|
|
AuthRoute --> PasswordUtil
|
|
|
|
|
|
AuthRoute --> RespUtil
|
|
|
|
|
|
RequestUtil --> AuthUtil
|
|
|
|
|
|
Router --> AuthUtil
|
|
|
|
|
|
Router --> TabsUtil
|
|
|
|
|
|
AuthRoute --> AuthMW
|
2026-07-10 16:51:05 +08:00
|
|
|
|
LoginView --> Styles
|
2026-06-30 14:46:52 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:100-151](file://frontend/src/views/login/index.vue#L100-L151)
|
|
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/views/login/index.vue:1-445](file://frontend/src/views/login/index.vue#L1-L445)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:1-99](file://frontend/src/utils/auth.js#L1-L99)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css:1-1259](file://frontend/src/styles/lux-theme.css#L1-L1259)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
|
|
|
|
|
|
## 核心组件
|
|
|
|
|
|
- 登录视图:负责表单渲染、字段校验、提交处理与成功/失败反馈。
|
|
|
|
|
|
- 认证 API:封装登录接口调用,统一请求参数格式。
|
|
|
|
|
|
- 认证工具:负责本地 Token 与用户信息的读取、设置、清理与解析。
|
|
|
|
|
|
- 请求封装:全局注入 Authorization 头、处理 401 自动跳转登录。
|
|
|
|
|
|
- 路由守卫:控制访问权限、超时自动登出、超级管理员限制。
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- 主题样式:提供统一的按钮样式、玻璃拟态效果和视觉规范。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 后端认证路由:处理登录、获取当前用户、修改密码。
|
|
|
|
|
|
- JWT 工具:签发与解码 Access Token,定义 TTL。
|
|
|
|
|
|
- 密码工具:PBKDF2 哈希与安全比对。
|
|
|
|
|
|
- 认证中间件:校验 Bearer Token 并注入用户上下文。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:100-151](file://frontend/src/views/login/index.vue#L100-L151)
|
|
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:1-99](file://frontend/src/utils/auth.js#L1-L99)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/auth.js:24-77](file://backend/src/routes/auth.js#L24-L77)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
|
|
|
|
|
|
## 架构总览
|
|
|
|
|
|
登录流程在前后端之间形成闭环:前端收集凭据并发起登录请求,后端验证用户与密码,签发 JWT,前端保存 Token 并重定向到首页;后续请求通过请求拦截器携带 Token,后端中间件校验并注入用户信息。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant U as "用户"
|
|
|
|
|
|
participant LV as "登录视图<br/>index.vue"
|
|
|
|
|
|
participant API as "认证 API<br/>auth.js"
|
|
|
|
|
|
participant REQ as "请求封装<br/>request.js"
|
|
|
|
|
|
participant AR as "认证路由<br/>routes/auth.js"
|
|
|
|
|
|
participant PW as "密码工具<br/>password.js"
|
|
|
|
|
|
participant JW as "JWT 工具<br/>jwt.js"
|
|
|
|
|
|
participant AU as "认证工具<br/>utils/auth.js"
|
|
|
|
|
|
participant RT as "路由守卫<br/>router/index.js"
|
|
|
|
|
|
U->>LV : 输入账号/密码并点击登录
|
|
|
|
|
|
LV->>LV : 表单校验
|
|
|
|
|
|
LV->>API : 调用登录接口
|
|
|
|
|
|
API->>REQ : 发送 POST /api/auth/login
|
|
|
|
|
|
REQ->>AR : 携带 Authorization非登录时
|
|
|
|
|
|
AR->>PW : 验证密码
|
|
|
|
|
|
AR->>JW : 签发 Access Token
|
|
|
|
|
|
AR-->>REQ : 返回 {access_token, user, expires_in}
|
|
|
|
|
|
REQ-->>LV : 返回响应数据
|
|
|
|
|
|
LV->>AU : setToken(access_token)
|
|
|
|
|
|
LV->>AU : setUser(user)
|
|
|
|
|
|
LV->>RT : 清空标签页缓存并跳转首页
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:123-150](file://frontend/src/views/login/index.vue#L123-L150)
|
|
|
|
|
|
- [frontend/src/api/auth.js:3-12](file://frontend/src/api/auth.js#L3-L12)
|
|
|
|
|
|
- [frontend/src/utils/request.js:12-25](file://frontend/src/utils/request.js#L12-L25)
|
|
|
|
|
|
- [backend/src/routes/auth.js:24-64](file://backend/src/routes/auth.js#L24-L64)
|
|
|
|
|
|
- [backend/src/utils/password.js:16-34](file://backend/src/utils/password.js#L16-L34)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:7-17](file://backend/src/utils/jwt.js#L7-L17)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:8-26](file://frontend/src/utils/auth.js#L8-L26)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/router/index.js:82-85](file://frontend/src/router/index.js#L82-85)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 详细组件分析
|
|
|
|
|
|
|
|
|
|
|
|
### 登录视图(表单设计与交互)
|
|
|
|
|
|
- 表单字段:
|
|
|
|
|
|
- 账号:必填,自动去除首尾空白。
|
|
|
|
|
|
- 密码:必填,支持显示/隐藏切换,回车触发提交。
|
|
|
|
|
|
- 校验规则:账号与密码均为必填项。
|
|
|
|
|
|
- 提交流程:
|
|
|
|
|
|
- 触发校验,通过后进入加载态。
|
|
|
|
|
|
- 调用登录 API,接收响应后:
|
|
|
|
|
|
- 若返回 access_token,则保存 Token 与用户信息,清空标签页缓存,跳转首页。
|
|
|
|
|
|
- 否则提示失败消息。
|
|
|
|
|
|
- 最终关闭加载态。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
Start(["开始"]) --> Validate["表单校验"]
|
|
|
|
|
|
Validate --> Valid{"校验通过?"}
|
|
|
|
|
|
Valid --> |否| ShowError["显示错误提示"]
|
|
|
|
|
|
Valid --> |是| Loading["设置加载态"]
|
|
|
|
|
|
Loading --> CallAPI["调用登录 API"]
|
|
|
|
|
|
CallAPI --> RespOK{"响应包含 access_token?"}
|
|
|
|
|
|
RespOK --> |是| SaveToken["保存 Token 与用户信息"]
|
|
|
|
|
|
SaveToken --> ClearTabs["清空标签页缓存"]
|
|
|
|
|
|
ClearTabs --> Redirect["跳转首页"]
|
|
|
|
|
|
RespOK --> |否| Toast["提示失败消息"]
|
|
|
|
|
|
Toast --> End(["结束"])
|
|
|
|
|
|
Redirect --> End
|
|
|
|
|
|
ShowError --> End
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:118-150](file://frontend/src/views/login/index.vue#L118-L150)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:45-91](file://frontend/src/views/login/index.vue#L45-L91)
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:118-150](file://frontend/src/views/login/index.vue#L118-L150)
|
|
|
|
|
|
|
|
|
|
|
|
### 认证 API 与请求封装
|
|
|
|
|
|
- 认证 API:
|
|
|
|
|
|
- 登录接口:POST /api/auth/login,参数包含 username 与 password。
|
|
|
|
|
|
- 修改密码接口:PUT /api/auth/password,参数包含 old_password 与 new_password。
|
|
|
|
|
|
- 请求封装:
|
|
|
|
|
|
- 默认 baseURL 为 /api,超时 10 秒。
|
|
|
|
|
|
- 请求拦截器:非登录接口自动附加 Authorization: Bearer token。
|
|
|
|
|
|
- 响应拦截器:
|
|
|
|
|
|
- code=0 的业务错误:统一弹出错误提示并拒绝 Promise。
|
|
|
|
|
|
- 401 未授权:清除本地认证信息,跳转登录页并附带 redirect 参数。
|
|
|
|
|
|
- 403 无权限:提示无权限。
|
|
|
|
|
|
- 其他错误:统一提示网络错误。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant LV as "登录视图"
|
|
|
|
|
|
participant API as "认证 API"
|
|
|
|
|
|
participant REQ as "请求封装"
|
|
|
|
|
|
participant AR as "认证路由"
|
|
|
|
|
|
participant RESP as "响应拦截器"
|
|
|
|
|
|
LV->>API : login({username,password})
|
|
|
|
|
|
API->>REQ : request({url : '/auth/login', method : 'post'})
|
|
|
|
|
|
REQ->>AR : 发送请求
|
|
|
|
|
|
AR-->>REQ : 返回 {code,data,msg}
|
|
|
|
|
|
REQ->>RESP : 统一处理响应
|
|
|
|
|
|
RESP-->>LV : 成功数据或抛错
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/api/auth.js:3-12](file://frontend/src/api/auth.js#L3-L12)
|
|
|
|
|
|
- [frontend/src/utils/request.js:12-69](file://frontend/src/utils/request.js#L12-L69)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
|
|
|
|
|
|
### 认证工具(Token 与用户信息)
|
|
|
|
|
|
- Token 存储键名:localStorage 中的 dashboard_access_token。
|
|
|
|
|
|
- 用户信息存储键名:localStorage 中的 dashboard_user。
|
|
|
|
|
|
- 主要方法:
|
|
|
|
|
|
- 获取/设置/清除 Token。
|
|
|
|
|
|
- 设置/获取/清除 用户信息。
|
|
|
|
|
|
- 从 Token 解析用户信息(sub、username、is_super_admin)。
|
|
|
|
|
|
- 判断 Token 是否过期(基于 exp)。
|
|
|
|
|
|
- 清除认证信息并清空标签页缓存。
|
|
|
|
|
|
- 判断是否超级管理员。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
GetToken["获取 Token"] --> HasToken{"存在 Token?"}
|
|
|
|
|
|
HasToken --> |否| NullUser["返回 null 或兜底解析"]
|
|
|
|
|
|
HasToken --> |是| ParseExp["解析 exp 时间戳"]
|
|
|
|
|
|
ParseExp --> Expired{"是否过期?"}
|
|
|
|
|
|
Expired --> |是| Clear["清除认证信息"]
|
|
|
|
|
|
Expired --> |否| ReturnUser["返回用户信息"]
|
|
|
|
|
|
Clear --> NullUser
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/utils/auth.js:4-99](file://frontend/src/utils/auth.js#L4-L99)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/utils/auth.js:1-99](file://frontend/src/utils/auth.js#L1-L99)
|
|
|
|
|
|
|
|
|
|
|
|
### 后端认证路由与中间件
|
|
|
|
|
|
- 登录接口:
|
|
|
|
|
|
- 校验必填参数,去空白用户名。
|
|
|
|
|
|
- 查询用户并检查状态。
|
|
|
|
|
|
- 使用 PBKDF2 验证密码。
|
|
|
|
|
|
- 更新最近登录时间,签发 Access Token,返回用户信息与过期时间。
|
|
|
|
|
|
- 获取当前用户接口:受认证中间件保护,返回用户字典。
|
|
|
|
|
|
- 修改密码接口:校验旧密码与新密码长度,更新密码哈希。
|
|
|
|
|
|
- 认证中间件:
|
|
|
|
|
|
- 校验 Authorization 头是否以 Bearer 开头。
|
|
|
|
|
|
- 解码 JWT,注入 req.user(id、username、is_super_admin)。
|
|
|
|
|
|
- 处理过期与无效 Token 场景。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant CL as "客户端"
|
|
|
|
|
|
participant AR as "认证路由"
|
|
|
|
|
|
participant DB as "数据库模型"
|
|
|
|
|
|
participant PW as "密码工具"
|
|
|
|
|
|
participant JW as "JWT 工具"
|
|
|
|
|
|
CL->>AR : POST /api/auth/login
|
|
|
|
|
|
AR->>DB : 查找用户
|
|
|
|
|
|
AR->>PW : verifyPassword(password, hash)
|
|
|
|
|
|
PW-->>AR : 验证结果
|
|
|
|
|
|
AR->>DB : 更新最近登录时间
|
|
|
|
|
|
AR->>JW : createAccessToken(user)
|
|
|
|
|
|
JW-->>AR : 返回 access_token
|
|
|
|
|
|
AR-->>CL : 返回 {access_token,user,expires_in}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:24-64](file://backend/src/routes/auth.js#L24-L64)
|
|
|
|
|
|
- [backend/src/utils/password.js:16-34](file://backend/src/utils/password.js#L16-L34)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:7-17](file://backend/src/utils/jwt.js#L7-L17)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/routes/auth.js:24-112](file://backend/src/routes/auth.js#L24-L112)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
|
|
|
|
|
|
### 路由守卫与权限控制
|
|
|
|
|
|
- 守卫逻辑:
|
|
|
|
|
|
- 需要认证的路由:若无 Token 或已过期,清除认证并跳转登录页,附带 redirect。
|
|
|
|
|
|
- 超级管理员限制:当目标路由标记 requiresSuperAdmin 且当前用户非超级管理员时,重定向首页。
|
|
|
|
|
|
- 已登录用户访问 /login:若 Token 有效则重定向首页。
|
|
|
|
|
|
- 与认证工具配合:使用 isTokenExpired 与 isSuperAdmin 判断。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
Enter(["进入路由"]) --> NeedAuth{"需要认证?"}
|
|
|
|
|
|
NeedAuth --> |否| Next["放行"]
|
|
|
|
|
|
NeedAuth --> |是| HasToken{"有有效 Token?"}
|
|
|
|
|
|
HasToken --> |否| GoLogin["跳转登录并附带 redirect"]
|
|
|
|
|
|
HasToken --> |是| SuperReq{"需要超级管理员?"}
|
|
|
|
|
|
SuperReq --> |是| IsSuper{"当前用户是超级管理员?"}
|
|
|
|
|
|
IsSuper --> |否| Home["重定向首页"]
|
|
|
|
|
|
IsSuper --> |是| Next
|
|
|
|
|
|
GoLogin --> End(["结束"])
|
|
|
|
|
|
Home --> End
|
|
|
|
|
|
Next --> End
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:73-75](file://frontend/src/utils/auth.js#L73-L75)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/router/index.js:64-88](file://frontend/src/router/index.js#L64-L88)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:73-75](file://frontend/src/utils/auth.js#L73-L75)
|
|
|
|
|
|
|
|
|
|
|
|
### JWT 令牌机制
|
|
|
|
|
|
- 签发:
|
|
|
|
|
|
- Payload 包含 sub、username、is_super_admin、iat、exp。
|
|
|
|
|
|
- TTL 固定为 12 小时,exp 以秒计算。
|
|
|
|
|
|
- 校验:
|
|
|
|
|
|
- 中间件使用 HS256 算法验证签名与过期时间。
|
|
|
|
|
|
- 过期或无效时返回 401。
|
|
|
|
|
|
- 前端解析:
|
|
|
|
|
|
- 从 Token 解析 exp 并转换为毫秒时间戳判断过期。
|
|
|
|
|
|
- 支持从 Token 兜底解析用户信息(sub、username、is_super_admin)。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
classDiagram
|
|
|
|
|
|
class JWTUtil {
|
|
|
|
|
|
+createAccessToken(user)
|
|
|
|
|
|
+decodeToken(token)
|
|
|
|
|
|
+getTokenTtlSeconds()
|
|
|
|
|
|
}
|
|
|
|
|
|
class AuthMW {
|
|
|
|
|
|
+authMiddleware(req,res,next)
|
|
|
|
|
|
+requireSuperAdmin(req,res,next)
|
|
|
|
|
|
}
|
|
|
|
|
|
class AuthUtils {
|
|
|
|
|
|
+getUserFromToken(token)
|
|
|
|
|
|
+getTokenExpiresAt(token)
|
|
|
|
|
|
+isTokenExpired(token)
|
|
|
|
|
|
}
|
|
|
|
|
|
AuthMW --> JWTUtil : "校验 Token"
|
|
|
|
|
|
AuthUtils --> JWTUtil : "解析 payload"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:52-99](file://frontend/src/utils/auth.js#L52-L99)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [frontend/src/utils/auth.js:52-99](file://frontend/src/utils/auth.js#L52-L99)
|
|
|
|
|
|
|
|
|
|
|
|
### 安全措施
|
|
|
|
|
|
- 密码存储与校验:
|
|
|
|
|
|
- 使用 PBKDF2(迭代次数、盐、密钥长度、摘要算法)进行哈希。
|
|
|
|
|
|
- 安全比对采用定时常量时间比较,降低侧信道攻击风险。
|
|
|
|
|
|
- 传输安全:
|
|
|
|
|
|
- 所有非登录接口自动附加 Bearer Token,避免明文传输。
|
|
|
|
|
|
- 建议在生产环境启用 HTTPS。
|
|
|
|
|
|
- 会话管理:
|
|
|
|
|
|
- 前端仅保存 Token 与用户信息于 localStorage/sessionStorage。
|
|
|
|
|
|
- 401 时自动清除认证信息并跳转登录。
|
|
|
|
|
|
- 路由守卫在进入受保护路由前校验 Token 有效性。
|
|
|
|
|
|
- 防暴力破解(建议):
|
|
|
|
|
|
- 后端可引入速率限制与账户锁定策略(当前实现未见显式限制逻辑)。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [frontend/src/utils/request.js:44-59](file://frontend/src/utils/request.js#L44-L59)
|
|
|
|
|
|
- [frontend/src/router/index.js:68-73](file://frontend/src/router/index.js#L68-L73)
|
|
|
|
|
|
|
|
|
|
|
|
### 错误处理与用户体验
|
|
|
|
|
|
- 登录错误:
|
|
|
|
|
|
- 前端:表单校验失败提示;接口返回错误提示;异常捕获与日志输出。
|
|
|
|
|
|
- 后端:参数缺失、用户不存在/禁用、密码错误、内部异常均返回统一结构。
|
|
|
|
|
|
- 401 自动跳转:
|
|
|
|
|
|
- 响应拦截器检测 401,清除本地认证,跳转登录页并附带 redirect。
|
|
|
|
|
|
- 403 权限不足:
|
|
|
|
|
|
- 弹出提示并阻止导航。
|
|
|
|
|
|
- 加载态与交互:
|
|
|
|
|
|
- 登录按钮显示加载态,避免重复提交。
|
|
|
|
|
|
- 提示文案统一使用 Element Plus 的消息组件。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:123-150](file://frontend/src/views/login/index.vue#L123-L150)
|
|
|
|
|
|
- [frontend/src/utils/request.js:27-69](file://frontend/src/utils/request.js#L27-L69)
|
|
|
|
|
|
- [backend/src/utils/response.js:1-25](file://backend/src/utils/response.js#L1-L25)
|
|
|
|
|
|
|
|
|
|
|
|
### 移动端适配
|
|
|
|
|
|
- 视口与布局:
|
|
|
|
|
|
- 登录卡片最大宽度限制,保证在小屏设备上不拥挤。
|
|
|
|
|
|
- 使用相对单位与弹性布局,确保在不同屏幕尺寸下保持良好体验。
|
|
|
|
|
|
- 交互优化:
|
|
|
|
|
|
- 输入框自动聚焦与回车提交,减少移动端输入成本。
|
|
|
|
|
|
- 按钮尺寸与间距适中,便于触摸点击。
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/views/login/index.vue:153-445](file://frontend/src/views/login/index.vue#L153-L445)
|
|
|
|
|
|
|
|
|
|
|
|
### 按钮样式优化(新增)
|
|
|
|
|
|
**更新** 登录按钮样式已从复杂的渐变背景简化为纯色背景配合 backdrop-filter 模糊效果,在保持玻璃拟态美学的同时显著提升了性能表现。
|
|
|
|
|
|
|
|
|
|
|
|
- **样式实现**:
|
|
|
|
|
|
- 主按钮采用纯色背景 `rgba(56, 189, 248, 0.92)`,移除了复杂的渐变计算
|
|
|
|
|
|
- 保留 `backdrop-filter: blur(8px)` 模糊效果,维持玻璃质感
|
|
|
|
|
|
- 悬停状态使用更亮的纯色 `rgba(34, 211, 238, 0.95)`
|
|
|
|
|
|
- 添加了内阴影和高光效果增强立体感
|
|
|
|
|
|
|
|
|
|
|
|
- **性能优化**:
|
|
|
|
|
|
- 减少了渐变背景的渲染开销
|
|
|
|
|
|
- 简化了 CSS 计算复杂度
|
|
|
|
|
|
- 保持了流畅的交互动画
|
|
|
|
|
|
|
|
|
|
|
|
- **视觉效果**:
|
|
|
|
|
|
- 圆角设计 `border-radius: 999px` 营造现代感
|
|
|
|
|
|
- 多层阴影系统提供深度层次
|
|
|
|
|
|
- 平滑的过渡动画提升用户体验
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A["登录按钮样式"] --> B["纯色背景替代渐变"]
|
|
|
|
|
|
A --> C["保留 backdrop-filter 模糊"]
|
|
|
|
|
|
A --> D["优化阴影系统"]
|
|
|
|
|
|
B --> E["提升渲染性能"]
|
|
|
|
|
|
C --> F["维持玻璃质感"]
|
|
|
|
|
|
D --> G["增强视觉层次"]
|
|
|
|
|
|
E --> H["流畅交互体验"]
|
|
|
|
|
|
F --> H
|
|
|
|
|
|
G --> H
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**图表来源**
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:382-424](file://frontend/src/views/login/index.vue#L382-L424)
|
|
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:382-424](file://frontend/src/views/login/index.vue#L382-L424)
|
|
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 依赖关系分析
|
|
|
|
|
|
- 前端模块耦合:
|
|
|
|
|
|
- 登录视图依赖认证 API 与认证工具。
|
|
|
|
|
|
- 认证 API 依赖请求封装。
|
|
|
|
|
|
- 请求封装依赖认证工具(读取 Token)。
|
|
|
|
|
|
- 路由守卫依赖认证工具与标签页工具。
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- 登录视图依赖主题样式(按钮样式、玻璃拟态效果)。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 后端模块耦合:
|
|
|
|
|
|
- 认证路由依赖模型、密码工具、JWT 工具与响应封装。
|
|
|
|
|
|
- 认证中间件依赖 JWT 工具。
|
|
|
|
|
|
- 可能的循环依赖:
|
|
|
|
|
|
- 当前模块划分清晰,未发现循环依赖迹象。
|
|
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
|
graph LR
|
|
|
|
|
|
LV["登录视图"] --> API["认证 API"]
|
|
|
|
|
|
API --> REQ["请求封装"]
|
|
|
|
|
|
REQ --> AU["认证工具"]
|
|
|
|
|
|
RT["路由守卫"] --> AU
|
|
|
|
|
|
RT --> TU["标签页工具"]
|
2026-07-10 16:51:05 +08:00
|
|
|
|
LV --> ST["主题样式"]
|
2026-06-30 14:46:52 +08:00
|
|
|
|
AR["认证路由"] --> PW["密码工具"]
|
|
|
|
|
|
AR --> JW["JWT 工具"]
|
|
|
|
|
|
AR --> RU["响应封装"]
|
|
|
|
|
|
AR --> MW["认证中间件"]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
图表来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:100-151](file://frontend/src/views/login/index.vue#L100-L151)
|
|
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/utils/response.js:1-25](file://backend/src/utils/response.js#L1-L25)
|
|
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/views/login/index.vue:100-151](file://frontend/src/views/login/index.vue#L100-L151)
|
|
|
|
|
|
- [frontend/src/api/auth.js:1-24](file://frontend/src/api/auth.js#L1-L24)
|
|
|
|
|
|
- [frontend/src/utils/request.js:1-72](file://frontend/src/utils/request.js#L1-L72)
|
|
|
|
|
|
- [frontend/src/router/index.js:1-91](file://frontend/src/router/index.js#L1-L91)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/styles/lux-theme.css:447-477](file://frontend/src/styles/lux-theme.css#L447-L477)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- [backend/src/routes/auth.js:1-112](file://backend/src/routes/auth.js#L1-L112)
|
|
|
|
|
|
- [backend/src/utils/password.js:1-37](file://backend/src/utils/password.js#L1-L37)
|
|
|
|
|
|
- [backend/src/utils/jwt.js:1-28](file://backend/src/utils/jwt.js#L1-L28)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:1-36](file://backend/src/middleware/auth.js#L1-L36)
|
|
|
|
|
|
- [backend/src/utils/response.js:1-25](file://backend/src/utils/response.js#L1-L25)
|
|
|
|
|
|
|
|
|
|
|
|
## 性能考虑
|
|
|
|
|
|
- Token TTL:12 小时,平衡安全性与用户体验。
|
|
|
|
|
|
- 请求拦截器:避免重复设置 Authorization,减少不必要的网络开销。
|
|
|
|
|
|
- 前端解析:仅在需要时解析 Token,避免频繁计算。
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- **按钮样式优化**:
|
|
|
|
|
|
- 简化渐变背景为纯色,减少 CSS 计算开销
|
|
|
|
|
|
- 保留必要的 backdrop-filter 效果,平衡性能与视觉效果
|
|
|
|
|
|
- 优化阴影层级,减少重绘重排
|
2026-06-30 14:46:52 +08:00
|
|
|
|
- 建议优化:
|
|
|
|
|
|
- 对频繁访问的受保护接口,可在路由守卫中加入缓存策略(如短期缓存用户信息)。
|
|
|
|
|
|
- 后端可引入登录失败计数与临时封禁策略,缓解暴力破解风险。
|
|
|
|
|
|
|
|
|
|
|
|
## 故障排除指南
|
|
|
|
|
|
- 登录失败:
|
|
|
|
|
|
- 检查用户名/密码是否为空,确认后端返回的错误消息。
|
|
|
|
|
|
- 确认数据库中用户状态正常且密码哈希正确。
|
|
|
|
|
|
- 401 未授权:
|
|
|
|
|
|
- 检查请求头是否包含正确的 Bearer Token。
|
|
|
|
|
|
- 确认 Token 未过期,必要时重新登录。
|
|
|
|
|
|
- 403 无权限:
|
|
|
|
|
|
- 确认当前用户具备所需权限(超级管理员)。
|
|
|
|
|
|
- 页面跳转异常:
|
|
|
|
|
|
- 检查路由守卫逻辑与 redirect 参数传递。
|
|
|
|
|
|
- 确认标签页缓存清理是否成功。
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- **按钮样式问题**:
|
|
|
|
|
|
- 检查主题样式是否正确加载。
|
|
|
|
|
|
- 确认浏览器是否支持 backdrop-filter 属性。
|
|
|
|
|
|
- 验证 CSS 优先级冲突。
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
章节来源
|
|
|
|
|
|
- [frontend/src/utils/request.js:44-59](file://frontend/src/utils/request.js#L44-L59)
|
|
|
|
|
|
- [frontend/src/router/index.js:68-73](file://frontend/src/router/index.js#L68-L73)
|
|
|
|
|
|
- [backend/src/middleware/auth.js:21-25](file://backend/src/middleware/auth.js#L21-L25)
|
2026-07-10 16:51:05 +08:00
|
|
|
|
- [frontend/src/views/login/index.vue:382-424](file://frontend/src/views/login/index.vue#L382-L424)
|
2026-06-30 14:46:52 +08:00
|
|
|
|
|
|
|
|
|
|
## 结论
|
2026-07-10 16:51:05 +08:00
|
|
|
|
该登录系统从前端表单到后端认证形成完整的闭环,具备良好的可维护性与扩展性。前端通过统一的请求封装与路由守卫保障了安全性与用户体验;后端通过 PBKDF2 哈希与 JWT 机制提供了可靠的认证基础。**最新的按钮样式优化进一步提升了性能表现,在保持玻璃拟态美学的同时实现了更好的渲染效率**。建议在生产环境中补充速率限制与 HTTPS 等安全措施,并持续监控与优化登录流程的性能与稳定性。
|