优化更新

This commit is contained in:
2026-09-13 20:29:19 +08:00
parent d7a081e8b7
commit 74f41f651f
65 changed files with 1061 additions and 1321 deletions
+21 -44
View File
@@ -6,18 +6,18 @@
**授权(Authorization)**:基于 RBAC(基于角色的访问控制)模型设计,权限控制粒度细化至接口级。用户通过角色继承权限节点(如 `sys:position:add`),由 `@check_permission` 装饰器在路由层统一拦截校验,权限数据采用 Redis 缓存加速查询,管理员(`userId == 1`)自动放行。权限变更时,相关缓存主动失效,确保权限更新的实时性。
**防护(Protection)**:系统从多维度构建安全防护体系。限流中间件基于 Redis 滑动窗口算法,有效防御 CC 攻击和接口滥用;参数校验通过 WTForms Schema 自动拦截非法输入,防止 SQL 注入和 XSS 攻击;敏感密码采用 bcrypt 加盐哈希存储,即使数据库泄露也无法还原明文;演示模式下 `@check_demo` 装饰器统一拦截写操作,保护测试数据不被污染;跨域配置精确控制可信域名,防止 CSRF 攻击。
**防护(Protection)**:系统从多维度构建安全防护体系。参数校验通过 WTForms Schema 自动拦截非法输入,防止 SQL 注入和 XSS 攻击;敏感密码采用 bcrypt 加盐哈希存储,即使数据库泄露也无法还原明文;演示模式下 `@check_demo` 装饰器统一拦截写操作,保护测试数据不被污染;跨域配置精确控制可信域名,防止 CSRF 攻击。
**审计(Audit)**:系统提供完备的操作审计能力。操作日志中间件自动记录所有写操作(POST/PUT/DELETE/PATCH)的请求路径、参数、操作人、IP 地址及执行结果,存入 `flask_operation_log` 表;登录日志独立记录每次登录尝试(含 IP、User-Agent、登录状态),便于安全事件追溯与异常行为分析;定时任务每次执行记录至 `flask_job_log` 表,确保后台任务的执行过程可审计。
:::tip 安全设计原则
纵深防御:认证、授权、限流、参数校验多层防护,单一防线失效时仍有其他机制兜底
纵深防御:认证、授权、参数校验多层防护,单一防线失效时仍有其他机制兜底
最小权限:用户仅能访问已授权接口,角色权限按需分配,遵循"够用即可"原则
数据不落地:敏感信息(Token、密码)不在日志中明文记录,密码哈希不可逆
安全默认:框架默认配置为安全模式(如 DEBUG 关闭、限流开启),如需放宽需显式配置
安全默认:框架默认配置为安全模式(如 DEBUG 关闭),如需放宽需显式配置
:::
## 安全架构总览
@@ -29,7 +29,7 @@
│ ┌───────────────────────────────────────────────────────────────┐ │
│ │ 网络层防护 │ │
│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │ │
│ │ │ CORS │ │ 限流 │ │ XSS 防护 │ │ 上传体积限制 │ │ │
│ │ │ CORS │ │ XSS 防护 │ │ 上传体积限制 │ │ │
│ │ │ 跨域控制 │ │ 滑动窗口 │ │ 输入清洗 │ │ DoS 防御 │ │ │
│ │ └──────────┘ └──────────┘ └──────────┘ └──────────────┘ │ │
│ └───────────────────────────────────────────────────────────────┘ │
@@ -316,7 +316,7 @@ def verify_password(password: str, salt: str, hashed: str) -> bool:
# src/core/permission.py
from functools import wraps
from flask import request
from src.core.response import R
from src.core import response as R
from src.core.security import get_user_id
def check_permission(permission: str):
@@ -369,7 +369,7 @@ def invalidate_perm_cache(user_id: int):
# src/middleware/demo.py
from functools import wraps
from flask import current_app
from src.core.response import R
from src.core import response as R
def check_demo(func):
"""演示模式拦截装饰器,放在 @check_permission 之后、路由函数之前"""
@@ -390,39 +390,20 @@ def check_demo(func):
### CORS 跨域控制
```python
# src/middleware/cors.py
# src/app.py - create_app()
from flask_cors import CORS
from config import CORS_ALLOWED_ORIGINS
def register_cors(app):
CORS(app,
origins=CORS_ALLOWED_ORIGINS,
supports_credentials=True,
methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["Content-Type", "Authorization"])
if CORS_ALLOWED_ORIGINS:
allowed_origins = [origin.strip() for origin in CORS_ALLOWED_ORIGINS.split(',') if origin.strip()]
CORS(app, resources={r"/*": {"origins": allowed_origins}}, supports_credentials=True)
else:
CORS(app, resources={r"/*": {"origins": "*"}}, supports_credentials=False)
```
- 生产环境应配置具体的 `origins`,避免使用 `*`
- 开发环境可配置为 `http://localhost:8001`
### 请求限流
```python
# src/middleware/rate_limit.py
from flask import request
def rate_limit():
# 基于客户端 IP 的滑动窗口限流
client_ip = get_client_ip()
count = sliding_window_incr(redis, current_key, prev_key, ...)
if count > RATE_LIMIT_LIMIT:
return R.failed(msg="请求过于频繁,请稍后再试")
```
- 默认关闭,通过 `RATE_LIMIT_ENABLED=True` 启用
- 使用 Redis 滑动窗口计数器,消除固定窗口边界 2x 突发
- Redis 不可用时降级放行(fail-open)
- CORS 预检请求不计数
### XSS 防护
```python
@@ -450,17 +431,16 @@ def sanitize_html(content: str) -> str:
### 上传体积限制
```python
# src/middleware/upload_size.py
from flask import request
# src/modules/upload/service.py
from config import UPLOAD_MAX_SIZE_MB
def upload_size_limit():
content_length = request.headers.get('content-length')
if content_length and int(content_length) > MAX_UPLOAD_SIZE:
return R.failed(msg="上传文件超出大小限制")
max_size_bytes = UPLOAD_MAX_SIZE_MB * 1024 * 1024
if file_size > max_size_bytes:
raise BizError(f"文件大小超过限制,最大允许 {UPLOAD_MAX_SIZE_MB}MB")
```
- 按 `Content-Length` 提前拒绝超大请求体
- 避免超大 multipart 落临时盘后再由业务层校验
- 在业务层校验文件大小,通过 `UPLOAD_MAX_SIZE_MB` 环境变量配置上限
- 前端配合 `el-upload` 组件的 `beforeUpload` 钩子做前置校验
## 四、数据层防护
@@ -548,9 +528,6 @@ def operation_log():
| JWT 过期时间 | `JWT_EXPIRE_MINUTES` | 120 | Token 有效期(分钟) |
| 密码错误锁定 | — | 5 次/10 分钟 | 连续失败后锁定 |
| 验证码有效期 | — | 120 秒 | 验证码 Redis TTL |
| 限流开关 | `RATE_LIMIT_ENABLED` | False | 滑动窗口限流 |
| 限流阈值 | `RATE_LIMIT_LIMIT` | 100 | 每窗口最大请求数 |
| 限流窗口 | `RATE_LIMIT_WINDOW_SECONDS` | 60 | 窗口时长(秒) |
| CORS 源 | `CORS_ALLOWED_ORIGINS` | * | 允许的跨域源 |
| 上传限制 | `UPLOAD_MAX_SIZE_MB` | 10MB | 最大上传体积 |
| 演示模式 | `FLASK_DEMO` | False | 锁定写操作 |
@@ -567,4 +544,4 @@ def operation_log():
## 总结
项目的安全架构涵盖认证(JWT + 验证码 + 登录锁定 + Token 黑名单)、授权(RBAC + check_permission + check_demo)、防护(CORS + 限流 + XSS + 上传限制 + SQL 注入防护)、审计(操作日志 + 登录日志)四大领域。通过纵深防御策略,在网络层、认证层、授权层、数据层分别设置安全屏障,确保系统在面对各类安全威胁时具备足够的防护能力。生产部署时需特别关注 JWT 密钥强度、CORS 配置、HTTPS 启用等关键安全项。
项目的安全架构涵盖认证(JWT + 验证码 + 登录锁定 + Token 黑名单)、授权(RBAC + check_permission + check_demo)、防护(CORS + XSS + 上传限制 + SQL 注入防护)、审计(操作日志 + 登录日志)四大领域。通过纵深防御策略,在网络层、认证层、授权层、数据层分别设置安全屏障,确保系统在面对各类安全威胁时具备足够的防护能力。生产部署时需特别关注 JWT 密钥强度、CORS 配置、HTTPS 启用等关键安全项。