mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-10-14 13:06:51 +00:00
本批为 t10 → t13 → t15 三轮实现 + 一轮复核驳回整改的最终形态(pytest 83 passed / ruff clean,
已部署并线上验证)。
异常语义
- CustomException 默认状态码 500 → 400(约 433 处裸调用不再被计为服务端故障),
且「包装底层异常」的 130 处显式恢复 500;get_or_404 → 404;响应体结构不变
代码生成注入面(复核 blocker F1,二次修复)
- column_type 不再做字符串拼接:改为常量白名单派生(类型名 ∈ DB_TO_SQLALCHEMY ∪ {Boolean},
长度仅取数字/正则捕获),彻底移除 split("(")[1]
- 列类型加形状白名单;字符串/注释/文档字符串用 \uXXXX,标识符过 safe_ident(含 Python/JS 关键字),
.vue 文本与静态属性改 HTML 实体
- 落盘闸门由 ast.parse 升级为 assert_python_structure(语法 + 顶层语句白名单 + 与哨兵骨架逐节点比对)
与 assert_text_structure(.vue/.ts/.toml 行结构);U+2028/2029 与 C1 控制符纳入转义
安全默认值
- 生产 CORS 不再回落 ["*"](未配置即拒绝跨域,可选 CORS_STRICT_STARTUP 直接启动失败)
- OAUTH_ALLOWED_HOSTS 不再默认 "*";新增 ALLOW_LOCALHOST_HOSTS 控制 Host 校验范围
- ALLOWED_HOSTS 收窄为按配置派生;健康检查暴露 code_exec_enabled / cors_origins_configured
定时任务
- SCHEDULER_ALLOW_CODE_EXEC 默认 False;新增 builtin:<模块名>[.<函数名>] 内置处理器路线(不经 exec)
- 判定收敛到 describe_schedulability;列表返回 schedulable / unschedulable_reason;
启动 reconcile 与状态查询对「已启用但不可调度」打 WARN(去重、恢复后清除)
- 加固:内置处理器必须在本模块内定义或经 HANDLERS 声明,拒绝模块内导入的外部对象(复核 R1)
- 顺带修复:_WARNED_UNSCHEDULABLE 的 set.pop TypeError、job.next_run_time 缺失导致的列表 500
测试:新增 tests/test_generator_template_safety.py、test_security_defaults.py、
test_scheduler_schedulability.py(含恶意载荷、闸门红绿、静态护栏)
101 lines
5.5 KiB
Bash
101 lines
5.5 KiB
Bash
# ==================================
|
||
# 环境配置文件:修改名称example为.env.dev或.env.prod 修改内容:ENVIRONMENT、SECRET_KEY、DATABASE_PASSWORD、REDIS_PASSWORD、OPENAI_API_KEY
|
||
# ==================================
|
||
|
||
ENVIRONMENT = dev # prod
|
||
|
||
# 服务器配置
|
||
SERVER_HOST = localhost
|
||
SERVER_PORT = 8001
|
||
# 前置可信反向代理跳数:docker 部署默认单层 nginx(默认 1);后端直接暴露公网时填 0,防止 X-Forwarded-For 伪造
|
||
# TRUSTED_PROXY_HOPS = 1
|
||
|
||
# 文档配置
|
||
DEBUG = True
|
||
VERSION = 3.1.0
|
||
|
||
# 是否启用演示模式
|
||
DEMO_ENABLE = False
|
||
|
||
# 数据库配置:mysql-3306、postgres-5432、sqlite
|
||
DATABASE_TYPE = mysql
|
||
DATABASE_HOST = localhost
|
||
DATABASE_PORT = 3306
|
||
DATABASE_USER = root
|
||
DATABASE_PASSWORD = your_database_password
|
||
DATABASE_NAME = fastapiadmin
|
||
|
||
# Redis配置
|
||
REDIS_HOST = localhost
|
||
REDIS_PORT = 6379
|
||
REDIS_USER = ''
|
||
REDIS_PASSWORD = your_redis_password
|
||
REDIS_DB_NAME = 1
|
||
|
||
# 日志级别配置
|
||
LOGGER_LEVEL = DEBUG
|
||
|
||
# ================================================= #
|
||
# *************** 安全相关(生产必填)*************** #
|
||
# ================================================= #
|
||
# 令牌签名密钥:openssl rand -hex 32(更换后所有已签发令牌失效)
|
||
SECRET_KEY = change_me_generate_with_openssl_rand_hex_32
|
||
# 落库敏感数据加密主密钥:openssl rand -hex 32;留空则由 SECRET_KEY 派生
|
||
DATA_ENCRYPTION_KEY = ''
|
||
# 轮换前的旧主密钥(逗号分隔),仅用于解密历史密文
|
||
DATA_ENCRYPTION_OLD_KEYS = ''
|
||
# 生产跨域白名单(逗号分隔,如 https://admin.example.com,https://www.example.com)
|
||
# ⚠️ 生产留空 = 拒绝全部跨域请求(安全默认,不再回落通配 "*";同源部署不受影响)。
|
||
# 存在站外集成时必须显式列出域名;填 "*" 会被忽略(与 ALLOW_CREDENTIALS=True 组合不可接受)。
|
||
PROD_CORS_ORIGINS = ''
|
||
# 严格启动:true 时「生产未配置 PROD_CORS_ORIGINS」直接启动失败(默认 false 只打 warning)
|
||
CORS_STRICT_STARTUP = False
|
||
# 只信任该网段内的反向代理传来的 X-Forwarded-*(切勿使用 *)
|
||
FORWARDED_ALLOW_IPS = 10.255.178.0/24
|
||
# 演示模式:true 时禁止写操作
|
||
DEMO_ENABLE = False
|
||
|
||
# ================================================= #
|
||
# ******************* 定时任务 ******************* #
|
||
# ================================================= #
|
||
# 是否允许定时任务执行用户提交的代码块(exec,等同服务器代码执行权限)。
|
||
# ⚠️ 默认 False:调成 false(或保持默认)时,**所有「代码块型」节点任务都不会被调度**
|
||
# (注册/手动执行会返回明确错误:"服务已禁用定时任务代码执行…"),执行结果可在任务执行日志查看;
|
||
# 这只关闭 exec 能力,不影响调度器本身、也不影响无代码块的其它任务。
|
||
# 如确需该能力,请显式置为 true,并按最小权限授予任务管理权限。
|
||
SCHEDULER_ALLOW_CODE_EXEC = False
|
||
|
||
# ================================================= #
|
||
# ******************* 主机名校验 ******************* #
|
||
# ================================================= #
|
||
# 允许的 Host 头(逗号分隔的 JSON 数组);生产填真实域名
|
||
# ALLOWED_HOSTS = ["service.fastapiadmin.com", "*.fastapiadmin.com"]
|
||
# 容器内健康检查/本地直连需要 Host: localhost|127.0.0.1|[::1];生产不需要时置 False 收敛校验范围
|
||
ALLOW_LOCALHOST_HOSTS = True
|
||
# OAuth 回调域名白名单(**不再是通配符 "*"**);非生产默认额外放行本机与回环地址
|
||
# OAUTH_ALLOWED_HOSTS = ["service.fastapiadmin.com", "*.fastapiadmin.com", "localhost", "127.0.0.1", "[::1]"]
|
||
|
||
# 大模型配置
|
||
OPENAI_BASE_URL = https://api.deepseek.com
|
||
OPENAI_API_KEY = your_api_key
|
||
OPENAI_MODEL = deepseek-v4-flash
|
||
|
||
# ================================================= #
|
||
# *********** 升级说明(行为变更,请逐条确认)***********
|
||
# ================================================= #
|
||
# 1) SCHEDULER_ALLOW_CODE_EXEC 默认由 true 改为 false:升级后所有「代码块型」节点任务
|
||
# 不再被调度/执行,直至显式配置为 true。健康检查(/api/v1/monitor/health/check)新增
|
||
# code_exec_enabled 字段可用于确认当前生效值。
|
||
# 2) 生产 PROD_CORS_ORIGINS 未配置时不再回落通配 "*",而是拒绝全部跨域请求
|
||
# (同源部署不受影响)。健康检查新增 cors_origins_configured 字段;可用 CORS_STRICT_STARTUP=true
|
||
# 把它变成启动失败以便尽早发现。
|
||
# 3) 业务异常的 HTTP 状态码按语义返回:客户端可修正类为 4xx(参数/验证码 400、无权限 403、
|
||
# 资源不存在 404),包装底层异常的内部故障为 500(此前统一 500/后统一 400 均不正确)。
|
||
# 4) 代码生成器的列名必须是合法标识符(且不能是 Python 关键字 / JS 保留字),
|
||
# 列类型必须是「类型名 + 可选(长度[,精度]) + 可选[] + 可选 unsigned」的形状;
|
||
# 含引号/分号/任意自由文本的类型会被拒绝(ENUM/SET 会归一化为基名)。
|
||
# 5) 代码生成落盘前新增结构闸门:.py 产物必须与「哨兵值骨架」AST 一致,.vue/.ts/.toml 做行结构比对,
|
||
# 任何注入/转义缺口都会在写盘前报错,而不是写出可被启动期 import 的坏文件。
|
||
# 6) OAUTH_ALLOWED_HOSTS 默认不再是 "*";如需自定义请在对应环境中显式配置。
|
||
# 7) ALLOWED_HOSTS 默认不再无条件包含 localhost:由 ALLOW_LOCALHOST_HOSTS 控制(默认 True 以兼容容器健康检查)。
|