# 用户认证系统
**本文引用的文件**
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py)
- [backend/app/core/security.py](file://backend/app/core/security.py)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py)
- [backend/app/models/models.py](file://backend/app/models/models.py)
- [backend/app/core/config.py](file://backend/app/core/config.py)
- [backend/app/main.py](file://backend/app/main.py)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js)
- [frontend/src/api/request.js](file://frontend/src/api/request.js)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js)
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue)
- [backend/requirements.txt](file://backend/requirements.txt)
- [test_frontend_connection.py](file://test_frontend_connection.py)
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件面向“医院绩效系统”的用户认证子系统,提供从登录注册到权限校验、JWT 令牌管理、会话与状态管理、前后端交互流程、错误处理与安全策略的完整说明。内容覆盖后端 FastAPI 接口、前端 Vue/Element Plus 交互、Pinia 状态管理、以及数据库模型与安全策略。
## 项目结构
认证系统由后端 API 路由、安全模块、数据模型与 Pydantic Schema,以及前端请求封装、状态管理与登录界面组成。整体采用 OAuth2 密码模式,使用 JWT 进行无状态鉴权;前端通过 Axios 拦截器统一注入 Authorization 头,后端通过依赖注入解析令牌并校验用户状态。
```mermaid
graph TB
subgraph "前端"
FE_Login["Login.vue
登录界面"]
FE_Store["user.js
Pinia Store"]
FE_API_Auth["auth.js
认证接口封装"]
FE_Request["request.js
Axios 实例与拦截器"]
end
subgraph "后端"
BE_Main["main.py
应用入口与CORS"]
BE_Router_Auth["api/v1/auth.py
认证路由"]
BE_Security["core/security.py
JWT/密码/依赖"]
BE_Schema["schemas/schemas.py
认证数据模型"]
BE_Models["models/models.py
User/Menu 等模型"]
BE_Config["core/config.py
JWT/跨域/分页配置"]
end
FE_Login --> FE_Store
FE_Store --> FE_API_Auth
FE_API_Auth --> FE_Request
FE_Request --> BE_Main
BE_Main --> BE_Router_Auth
BE_Router_Auth --> BE_Security
BE_Security --> BE_Schema
BE_Security --> BE_Models
BE_Router_Auth --> BE_Schema
BE_Router_Auth --> BE_Models
BE_Main --> BE_Config
```
图表来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L1-L74)
- [backend/app/core/security.py](file://backend/app/core/security.py#L1-L110)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L313-L346)
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
- [backend/app/core/config.py](file://backend/app/core/config.py#L9-L38)
- [backend/app/main.py](file://backend/app/main.py#L15-L77)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L22)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L1-L66)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L49)
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L1-L155)
章节来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L1-L74)
- [backend/app/core/security.py](file://backend/app/core/security.py#L1-L110)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L313-L346)
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
- [backend/app/core/config.py](file://backend/app/core/config.py#L9-L38)
- [backend/app/main.py](file://backend/app/main.py#L15-L77)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L22)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L1-L66)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L49)
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L1-L155)
## 核心组件
- 认证路由与接口
- 登录:接收表单数据,校验用户名/密码与账户状态,签发 JWT。
- 注册:校验用户名唯一性,生成密码哈希,写入用户记录。
- 当前用户:基于依赖注入解析 JWT 并返回用户信息。
- 安全模块
- 密码哈希:bcrypt。
- JWT:encode/decode,OAuth2 密码流 tokenUrl。
- 依赖:获取当前用户、校验激活状态、校验管理员/经理角色。
- 数据模型与 Schema
- User 模型:id、username、password_hash、role、is_active、last_login 等。
- 认证 Schema:UserLogin、UserCreate、Token、UserResponse。
- 前端交互
- 登录表单:Element Plus 表单校验与按钮触发。
- Pinia Store:保存 token、持久化 localStorage、登出重定向。
- Axios 拦截器:自动注入 Authorization: Bearer token,401 跳转登录。
章节来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L74)
- [backend/app/core/security.py](file://backend/app/core/security.py#L24-L110)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L315-L346)
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L63-L89)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L10-L39)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L14-L26)
## 架构总览
认证系统遵循 OAuth2 密码模式,后端通过 FastAPI 的依赖注入解析 JWT,前端通过 Axios 拦截器统一携带 Bearer Token。CORS 在后端全局中间件开启,允许前端开发源访问。
```mermaid
sequenceDiagram
participant U as "用户浏览器"
participant LV as "Login.vue"
participant US as "user.js"
participant AU as "auth.js"
participant AX as "request.js"
participant API as "auth.py"
participant SEC as "security.py"
participant DB as "数据库"
U->>LV : 输入用户名/密码并点击登录
LV->>US : 调用 store.login(username, password)
US->>AU : 调用 login({username, password})
AU->>AX : POST /api/v1/auth/login (表单)
AX->>API : 发送请求
API->>SEC : verify_password() 校验密码
API->>DB : 查询用户并检查 is_active
API-->>AX : 返回 {access_token, token_type}
AX-->>US : 返回 access_token
US->>US : localStorage.setItem('token', access_token)
US-->>LV : 登录成功,跳转首页
```
图表来源
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L73-L89)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L4-L11)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L14-L26)
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L37)
- [backend/app/core/security.py](file://backend/app/core/security.py#L24-L31)
## 详细组件分析
### 后端认证路由与接口
- 登录接口
- 方法与路径:POST /api/v1/auth/login
- 请求体:OAuth2 表单(username/password),或前端封装为 application/x-www-form-urlencoded。
- 处理逻辑:查询用户、校验密码、检查 is_active、签发 access_token。
- 响应:Token 模型(access_token、token_type=bearer)。
- 注册接口
- 方法与路径:POST /api/v1/auth/register
- 请求体:UserCreate(username、password、staff_id、role)。
- 处理逻辑:检查用户名唯一性、生成密码哈希、写入 User 记录。
- 响应:通用响应(code/message/data)。
- 当前用户接口
- 方法与路径:GET /api/v1/auth/me
- 依赖:get_current_active_user(校验令牌与激活状态)。
- 响应:UserResponse。
章节来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L74)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L315-L346)
### 安全模块与 JWT 策略
- OAuth2 密码模式
- tokenUrl:/api/v1/auth/login。
- 前端通过 OAuth2PasswordRequestForm 或自定义表单提交。
- 密码与令牌
- 密码哈希:bcrypt。
- 令牌载荷:sub(用户 id)、exp(过期时间)。
- 算法与密钥:配置项 ALGORITHM/SECRET_KEY。
- 依赖链
- get_current_user:从 Authorization 解析 JWT,查询用户。
- get_current_active_user:校验 is_active。
- get_current_admin_user / get_current_manager_user:校验角色。
- 配置
- ACCESS_TOKEN_EXPIRE_MINUTES:默认约 8 小时。
- API_PREFIX:/api/v1。
章节来源
- [backend/app/core/security.py](file://backend/app/core/security.py#L21-L110)
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
- [backend/app/main.py](file://backend/app/main.py#L41-L48)
### 数据模型与权限枚举
- User 模型字段
- id、username(唯一)、password_hash、role、is_active、last_login、created_at/updated_at。
- 角色与权限
- role:admin(管理员)、manager(经理)、staff(普通员工)。
- 依赖 get_current_manager_user 用于限制“管理员或经理”操作。
- 菜单与权限标识
- Menu 模型含 permission 字段,可用于前端菜单/按钮级权限控制(与后端依赖配合)。
章节来源
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
- [backend/app/core/security.py](file://backend/app/core/security.py#L94-L109)
- [backend/app/models/models.py](file://backend/app/models/models.py#L347-L372)
### 前端交互与状态管理
- 登录界面
- Element Plus 表单校验、输入框、按钮与回车事件。
- Axios 拦截器
- 请求:自动注入 Authorization: Bearer token。
- 响应:401 清除本地 token 并跳转登录页。
- Pinia Store
- 登录:调用后端登录接口,保存 token 到内存与 localStorage。
- 获取用户:调用 /auth/me,缓存用户信息。
- 登出:清除 token 与用户信息,移除 localStorage,跳转登录页。
章节来源
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L63-L89)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L14-L26)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L10-L39)
### API 接口定义与参数说明
- 登录
- 方法:POST
- 路径:/api/v1/auth/login
- 认证:OAuth2 表单或 application/x-www-form-urlencoded
- 请求体字段:username、password
- 响应体字段:access_token、token_type
- 注册
- 方法:POST
- 路径:/api/v1/auth/register
- 请求体字段:username、password、staff_id、role
- 响应体字段:code、message、data.id
- 当前用户
- 方法:GET
- 路径:/api/v1/auth/me
- 认证:Authorization: Bearer
- 响应体字段:id、username、role、is_active、last_login、created_at
章节来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L74)
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py#L315-L346)
### 错误处理与安全防护
- 后端错误
- 401 未授权:凭据无效或令牌解析失败。
- 403 禁止访问:账户被禁用或权限不足。
- 400 参数错误:用户名已存在、用户不存在等。
- 前端错误
- 401:提示“登录已过期,请重新登录”,清除 token 并跳转登录页。
- 通用错误:弹出 ElMessage 提示。
- 安全策略
- 密码使用 bcrypt 哈希。
- JWT 使用 HS256 算法与强密钥(生产环境需替换默认密钥)。
- CORS 允许指定前端源。
- 令牌过期时间可配置,默认约 8 小时。
章节来源
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L30-L34)
- [backend/app/core/security.py](file://backend/app/core/security.py#L55-L91)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L38-L62)
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
- [backend/app/main.py](file://backend/app/main.py#L41-L48)
## 依赖分析
- 后端依赖
- FastAPI + SQLAlchemy 异步 + Pydantic + python-jose + bcrypt。
- CORS 中间件开启,允许前端开发源。
- 前端依赖
- axios、Element Plus、Vue Router、Pinia。
- 认证依赖链
- auth.py 依赖 security.py 的 verify_password、create_access_token、get_current_active_user。
- security.py 依赖 config.py 的 SECRET_KEY、ALGORITHM、ACCESS_TOKEN_EXPIRE_MINUTES。
- 前端 auth.js 依赖 request.js 的 baseURL 与拦截器。
```mermaid
graph LR
RQ["requirements.txt
依赖声明"] --> BE_SEC["security.py"]
BE_MAIN["main.py"] --> BE_AUTH["auth.py"]
BE_AUTH --> BE_SEC
BE_SEC --> BE_CFG["config.py"]
FE_REQ["request.js"] --> FE_AUTH["auth.js"]
FE_AUTH --> FE_STORE["user.js"]
FE_STORE --> FE_LOGIN["Login.vue"]
```
图表来源
- [backend/requirements.txt](file://backend/requirements.txt#L1-L17)
- [backend/app/main.py](file://backend/app/main.py#L41-L48)
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L10-L12)
- [backend/app/core/security.py](file://backend/app/core/security.py#L13-L15)
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L6-L12)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L2)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L4)
章节来源
- [backend/requirements.txt](file://backend/requirements.txt#L1-L17)
- [backend/app/main.py](file://backend/app/main.py#L41-L48)
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L10-L12)
- [backend/app/core/security.py](file://backend/app/core/security.py#L13-L15)
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L6-L12)
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L2)
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L4)
## 性能考虑
- 令牌有效期:默认约 8 小时,建议根据业务场景调整,避免频繁刷新。
- 密码哈希:bcrypt 默认成本适中,生产环境可根据硬件能力提升成本。
- 数据库连接池:配置 DATABASE_POOL_SIZE 与 MAX_OVERFLOW,确保高并发下的连接稳定性。
- 前端拦截器:统一注入 Authorization,减少重复代码与错误。
## 故障排查指南
- 登录失败
- 确认用户名/密码正确,账户处于激活状态。
- 检查后端日志与 401/403 错误原因。
- CORS 问题
- 确认后端 CORS_ORIGINS 包含前端地址,测试脚本验证 OPTIONS 预检。
- Token 过期或 401
- 前端拦截器会自动清除 token 并跳转登录页,重新登录获取新令牌。
- 本地开发
- 前端通过 Vite 代理访问后端 /api,确保 baseURL 与后端 API_PREFIX 一致。
章节来源
- [test_frontend_connection.py](file://test_frontend_connection.py#L38-L74)
- [frontend/src/api/request.js](file://frontend/src/api/request.js#L38-L62)
- [backend/app/main.py](file://backend/app/main.py#L41-L48)
## 结论
该认证系统采用 OAuth2 密码模式与 JWT 无状态鉴权,结合 bcrypt 密码哈希与严格的依赖校验,实现了登录注册、权限控制与会话管理。前端通过 Axios 拦截器与 Pinia Store 完成令牌注入与状态维护,整体结构清晰、扩展性强,适合在医院绩效系统中作为统一认证层使用。
## 附录
- 默认凭证
- 用户名:admin
- 密码:admin123
- API 文档
- Swagger UI:http://localhost:8000/api/v1/docs
- ReDoc:http://localhost:8000/api/v1/redoc