提交文件
This commit is contained in:
339
.qoder/repowiki/zh/content/核心功能模块/用户认证系统.md
Normal file
339
.qoder/repowiki/zh/content/核心功能模块/用户认证系统.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# 用户认证系统
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [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)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
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<br/>登录界面"]
|
||||
FE_Store["user.js<br/>Pinia Store"]
|
||||
FE_API_Auth["auth.js<br/>认证接口封装"]
|
||||
FE_Request["request.js<br/>Axios 实例与拦截器"]
|
||||
end
|
||||
subgraph "后端"
|
||||
BE_Main["main.py<br/>应用入口与CORS"]
|
||||
BE_Router_Auth["api/v1/auth.py<br/>认证路由"]
|
||||
BE_Security["core/security.py<br/>JWT/密码/依赖"]
|
||||
BE_Schema["schemas/schemas.py<br/>认证数据模型"]
|
||||
BE_Models["models/models.py<br/>User/Menu 等模型"]
|
||||
BE_Config["core/config.py<br/>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 <token>
|
||||
- 响应体字段: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<br/>依赖声明"] --> 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
|
||||
Reference in New Issue
Block a user