提交文件
This commit is contained in:
357
.qoder/repowiki/zh/content/业务逻辑设计/权限控制机制.md
Normal file
357
.qoder/repowiki/zh/content/业务逻辑设计/权限控制机制.md
Normal file
@@ -0,0 +1,357 @@
|
||||
# 权限控制机制
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py)
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py)
|
||||
- [backend/app/schemas/schemas.py](file://backend/app/schemas/schemas.py)
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py)
|
||||
- [backend/app/services/staff_service.py](file://backend/app/services/staff_service.py)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py)
|
||||
- [backend/app/services/menu_service.py](file://backend/app/services/menu_service.py)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py)
|
||||
- [backend/app/main.py](file://backend/app/main.py)
|
||||
- [backend/app/core/logging_config.py](file://backend/app/core/logging_config.py)
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件系统化阐述医院绩效系统的权限控制机制,重点覆盖基于角色的访问控制(RBAC)实现、菜单权限与数据权限设计、JWT令牌验证、用户角色分配与权限继承机制。文档同时给出不同角色(管理员、科室负责人、普通员工)的权限范围与操作限制,解释后端中间件式权限校验、动态权限检查与安全审计日志策略,并提供权限配置的扩展方式、权限矩阵与安全最佳实践。
|
||||
|
||||
## 项目结构
|
||||
后端采用 FastAPI + SQLAlchemy 异步 ORM 的分层架构,权限控制相关代码主要集中在以下模块:
|
||||
- 安全与认证:core/security.py、api/v1/auth.py、core/config.py
|
||||
- 数据模型:models/models.py(含用户、菜单等)
|
||||
- 前端路由守卫:frontend/src/router/index.js(令牌拦截)
|
||||
- 日志与审计:core/logging_config.py
|
||||
- API 路由聚合:api/v1/__init__.py
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "后端"
|
||||
A["main.py<br/>应用入口与CORS"]
|
||||
B["api/v1/__init__.py<br/>路由聚合"]
|
||||
C["core/security.py<br/>JWT与权限依赖"]
|
||||
D["api/v1/auth.py<br/>登录/注册/当前用户"]
|
||||
E["models/models.py<br/>User/Menu等模型"]
|
||||
F["core/config.py<br/>JWT配置"]
|
||||
G["core/logging_config.py<br/>日志与审计"]
|
||||
end
|
||||
subgraph "前端"
|
||||
H["frontend/src/router/index.js<br/>路由守卫"]
|
||||
end
|
||||
H --> A
|
||||
A --> B
|
||||
B --> D
|
||||
D --> C
|
||||
C --> E
|
||||
C --> F
|
||||
A --> G
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/main.py](file://backend/app/main.py#L15-L77)
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py#L1-L17)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L1-L110)
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L1-L74)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
|
||||
- [backend/app/core/logging_config.py](file://backend/app/core/logging_config.py#L1-L65)
|
||||
|
||||
章节来源
|
||||
- [backend/app/main.py](file://backend/app/main.py#L15-L77)
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py#L1-L17)
|
||||
|
||||
## 核心组件
|
||||
- JWT 与令牌管理:负责令牌签发、解码、过期控制与用户解析。
|
||||
- 权限依赖注入:提供“当前用户”、“当前有效用户”、“管理员”、“管理员或经理”的依赖函数,作为路由装饰器实现中间件式权限控制。
|
||||
- 用户模型与角色:User 模型包含 role 字段,支持 admin、manager、staff 角色。
|
||||
- 菜单模型与权限标识:Menu 模型包含 permission 字段,用于前端按钮级权限标识。
|
||||
- 员工与菜单 API:通过依赖注入实现不同角色的访问控制。
|
||||
|
||||
章节来源
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L34-L110)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L347-L373)
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L109)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L98-L150)
|
||||
|
||||
## 架构总览
|
||||
后端通过 FastAPI 的依赖注入系统,在每个路由上声明所需的权限依赖,实现“中间件式”的权限控制。前端通过路由守卫拦截未登录访问,后端通过 OAuth2 Bearer 令牌进行鉴权。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as "前端"
|
||||
participant API as "FastAPI路由"
|
||||
participant SEC as "security依赖"
|
||||
participant DB as "数据库"
|
||||
participant MOD as "模型(User)"
|
||||
FE->>API : "携带Authorization : Bearer token"
|
||||
API->>SEC : "依赖注入 : get_current_user()"
|
||||
SEC->>SEC : "decode_token()"
|
||||
SEC->>DB : "按ID查询用户"
|
||||
DB-->>SEC : "返回User"
|
||||
SEC->>MOD : "校验is_active"
|
||||
MOD-->>API : "返回当前用户"
|
||||
API-->>FE : "执行业务逻辑/返回数据"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L55-L91)
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L37)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### JWT 与令牌验证
|
||||
- 令牌签发:使用 HS256 算法,包含 exp 与 sub(用户ID),默认有效期 8 小时。
|
||||
- 令牌解码:验证签名与过期时间,失败则抛出凭据无效异常。
|
||||
- 用户解析:从载荷提取 sub(用户ID),查询数据库获取用户实体并校验 is_active。
|
||||
- 依赖链路:OAuth2PasswordBearer 提供 tokenUrl,get_current_user 解析用户,get_current_active_user 进一步校验状态。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入受保护路由"]) --> GetToken["从Authorization头获取Bearer token"]
|
||||
GetToken --> Decode["decode_token() 验证签名与过期"]
|
||||
Decode --> Valid{"解码成功?"}
|
||||
Valid --> |否| Raise401["抛出401未授权"]
|
||||
Valid --> |是| LoadUser["按ID查询User"]
|
||||
LoadUser --> Active{"is_active=true?"}
|
||||
Active --> |否| Raise403["抛出403禁止访问"]
|
||||
Active --> |是| ReturnUser["返回当前用户"]
|
||||
Raise401 --> End(["结束"])
|
||||
Raise403 --> End
|
||||
ReturnUser --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L34-L91)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
|
||||
|
||||
章节来源
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L34-L91)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
|
||||
|
||||
### RBAC 角色与权限继承
|
||||
- 角色定义:User.role 支持 admin(管理员)、manager(经理)、staff(普通员工)。
|
||||
- 权限依赖:
|
||||
- get_current_active_user:校验用户激活状态。
|
||||
- get_current_manager_user:要求 admin 或 manager。
|
||||
- get_current_admin_user:要求 admin。
|
||||
- 路由装饰示例:
|
||||
- 员工管理:创建/更新/删除需管理员或经理权限。
|
||||
- 菜单管理:创建/更新/删除需管理员或经理权限;初始化默认菜单需管理员权限。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class User {
|
||||
+int id
|
||||
+string username
|
||||
+string role
|
||||
+bool is_active
|
||||
}
|
||||
class SecurityDeps {
|
||||
+get_current_user(token) User
|
||||
+get_current_active_user(user) User
|
||||
+get_current_manager_user(user) User
|
||||
+get_current_admin_user(user) User
|
||||
}
|
||||
class StaffAPI {
|
||||
+create_staff() Response
|
||||
+update_staff() Response
|
||||
+delete_staff() Response
|
||||
}
|
||||
class MenuAPI {
|
||||
+create_menu() Response
|
||||
+update_menu() Response
|
||||
+delete_menu() Response
|
||||
+init_default_menus() Response
|
||||
}
|
||||
StaffAPI --> SecurityDeps : "依赖manager/admin"
|
||||
MenuAPI --> SecurityDeps : "依赖manager/admin"
|
||||
SecurityDeps --> User : "返回当前用户"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L85-L110)
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L109)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L98-L150)
|
||||
|
||||
章节来源
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L85-L110)
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L109)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L98-L150)
|
||||
|
||||
### 菜单权限与前端集成
|
||||
- 菜单模型:Menu 包含 permission 字段,用于前端按钮级权限标识。
|
||||
- 菜单服务:提供树形结构、列表查询、默认初始化等能力。
|
||||
- 前端路由守卫:未登录访问会被重定向至登录页,确保前端侧最小暴露面。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as "前端"
|
||||
participant API as "菜单API"
|
||||
participant SVC as "MenuService"
|
||||
participant DB as "数据库"
|
||||
FE->>API : "GET /menus/tree?visible_only=true"
|
||||
API->>SVC : "get_tree(visible_only)"
|
||||
SVC->>DB : "查询可见且启用的菜单树"
|
||||
DB-->>SVC : "返回菜单树"
|
||||
SVC-->>API : "返回树形结构"
|
||||
API-->>FE : "渲染菜单树/按钮权限"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L17-L29)
|
||||
- [backend/app/services/menu_service.py](file://backend/app/services/menu_service.py#L16-L29)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L347-L373)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L17-L29)
|
||||
- [backend/app/services/menu_service.py](file://backend/app/services/menu_service.py#L16-L29)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L347-L373)
|
||||
|
||||
### 数据权限与业务边界
|
||||
- 员工管理:仅管理员或经理可增删改;查询列表对所有有效用户开放。
|
||||
- 菜单管理:对菜单树与列表查询不强制管理员权限,但对写操作(创建/更新/删除/初始化)要求管理员或经理。
|
||||
- 建议扩展:可在服务层增加“数据域过滤”,例如按用户关联的 staff_id 或 department_id 限制查询范围,避免越权访问。
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L20-L49)
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L109)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L32-L65)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L98-L150)
|
||||
|
||||
### 认证流程与注册
|
||||
- 登录:用户名+密码校验,账户激活状态校验,成功后签发访问令牌。
|
||||
- 注册:校验用户名唯一性,生成密码哈希,创建用户并返回结果。
|
||||
- 当前用户:通过 /api/v1/auth/me 获取当前用户信息。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as "前端"
|
||||
participant AUTH as "Auth路由"
|
||||
participant SEC as "security"
|
||||
participant DB as "数据库"
|
||||
FE->>AUTH : "POST /auth/login"
|
||||
AUTH->>DB : "按用户名查询用户"
|
||||
DB-->>AUTH : "返回User"
|
||||
AUTH->>SEC : "verify_password()"
|
||||
SEC-->>AUTH : "校验通过"
|
||||
AUTH->>SEC : "create_access_token(user.id)"
|
||||
SEC-->>AUTH : "返回access_token"
|
||||
AUTH-->>FE : "{access_token, token_type}"
|
||||
FE->>AUTH : "GET /auth/me"
|
||||
AUTH->>SEC : "get_current_active_user"
|
||||
SEC->>DB : "查询当前用户"
|
||||
DB-->>SEC : "返回User"
|
||||
SEC-->>AUTH : "返回当前用户"
|
||||
AUTH-->>FE : "用户信息"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L73)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L24-L43)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L55-L91)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L73)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L24-L43)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L55-L91)
|
||||
|
||||
### 安全审计与日志
|
||||
- 日志配置:按天轮转 app_error 日志,区分控制台与文件输出等级。
|
||||
- 异常处理:全局 HTTP 与验证异常记录到日志,便于审计与追踪。
|
||||
- 建议:在权限决策点(如 get_current_manager_user)增加审计日志,记录用户ID、操作、IP、时间与结果。
|
||||
|
||||
章节来源
|
||||
- [backend/app/core/logging_config.py](file://backend/app/core/logging_config.py#L1-L65)
|
||||
- [backend/app/main.py](file://backend/app/main.py#L58-L74)
|
||||
|
||||
## 依赖关系分析
|
||||
- 路由聚合:api/v1/__init__.py 将各模块路由统一挂载到主应用。
|
||||
- 中间件:main.py 配置 CORS,确保前后端跨域通信。
|
||||
- 安全依赖:security.py 的依赖函数被各业务路由复用,形成统一的权限控制入口。
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
INIT["api/v1/__init__.py"] --> AUTH["api/v1/auth.py"]
|
||||
INIT --> STAFF["api/v1/staff.py"]
|
||||
INIT --> MENUS["api/v1/menus.py"]
|
||||
MAIN["main.py"] --> INIT
|
||||
AUTH --> SEC["core/security.py"]
|
||||
STAFF --> SEC
|
||||
MENUS --> SEC
|
||||
SEC --> CFG["core/config.py"]
|
||||
SEC --> MODELS["models/models.py"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py#L1-L17)
|
||||
- [backend/app/main.py](file://backend/app/main.py#L41-L51)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L1-L110)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L23-L26)
|
||||
- [backend/app/models/models.py](file://backend/app/models/models.py#L244-L261)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/__init__.py](file://backend/app/api/v1/__init__.py#L1-L17)
|
||||
- [backend/app/main.py](file://backend/app/main.py#L41-L51)
|
||||
|
||||
## 性能考虑
|
||||
- 令牌解码与用户查询:建议在网关或中间件层缓存近期活跃用户的轻量信息,减少数据库查询压力。
|
||||
- 分页与索引:员工与菜单查询使用分页与索引,避免大结果集扫描。
|
||||
- CORS 与异常处理:合理配置允许的源与方法,减少预检请求开销。
|
||||
|
||||
## 故障排查指南
|
||||
- 401 未授权:检查 Authorization 头是否携带 Bearer token,确认 token 未过期。
|
||||
- 403 禁止访问:确认用户角色满足 get_current_manager_user 或 get_current_admin_user 要求。
|
||||
- 登录失败:检查用户名/密码与账户激活状态。
|
||||
- 跨域问题:确认 CORS_ORIGINS 配置与前端访问地址一致。
|
||||
|
||||
章节来源
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L55-L110)
|
||||
- [backend/app/api/v1/auth.py](file://backend/app/api/v1/auth.py#L17-L37)
|
||||
- [backend/app/core/config.py](file://backend/app/core/config.py#L28-L29)
|
||||
|
||||
## 结论
|
||||
该系统采用简洁明确的 RBAC 模式:以角色驱动的依赖注入实现中间件式权限控制,结合 JWT 令牌与用户激活状态校验,满足后台管理场景下的安全需求。菜单模型的 permission 字段为前端按钮级权限提供了基础。建议后续在服务层引入数据域过滤与权限审计日志,进一步强化数据权限与合规性。
|
||||
|
||||
## 附录
|
||||
|
||||
### 角色权限矩阵(摘要)
|
||||
- 管理员(admin)
|
||||
- 员工管理:创建/更新/删除
|
||||
- 菜单管理:创建/更新/删除/初始化
|
||||
- 科室负责人(manager)
|
||||
- 员工管理:创建/更新/删除
|
||||
- 菜单管理:创建/更新/删除(不含初始化)
|
||||
- 普通员工(staff)
|
||||
- 员工管理:仅查询列表与详情
|
||||
- 菜单管理:查询菜单树/列表(写操作受限)
|
||||
|
||||
章节来源
|
||||
- [backend/app/api/v1/staff.py](file://backend/app/api/v1/staff.py#L68-L109)
|
||||
- [backend/app/api/v1/menus.py](file://backend/app/api/v1/menus.py#L98-L150)
|
||||
- [backend/app/core/security.py](file://backend/app/core/security.py#L85-L110)
|
||||
|
||||
### 安全最佳实践
|
||||
- 强制使用 HTTPS 传输,避免令牌在传输中泄露。
|
||||
- 生产环境更换 SECRET_KEY,定期轮换。
|
||||
- 严格限制 CORS 源,避免跨站风险。
|
||||
- 对高敏感操作(如删除)增加二次确认与审计日志。
|
||||
- 在服务层增加数据域过滤,防止越权读取。
|
||||
Reference in New Issue
Block a user