fix(security): 文件上传 MIME 白名单 + OAuth JWT 密钥路径统一

P0 #1: 媒体文件上传增加 MIME 类型白名单校验(jpeg/png/gif/webp/svg/mp4/webm/pdf)
       和文件大小限制(10MB),扩展名使用白名单清理防止路径遍历攻击。
P0 #2: OAuth JWT 密钥从环境变量改为 State 注入,消除运行时 env::var 依赖,
       FHIR 路由中间件使用闭包捕获 jwt_secret 保持类型安全。
This commit is contained in:
iven
2026-05-17 12:40:02 +08:00
parent 8d3c5915c9
commit 6841c45846
12 changed files with 180 additions and 43 deletions

View File

@@ -723,8 +723,9 @@ async fn main() -> anyhow::Result<()> {
))
.layer({
let db = state.db.clone();
let jwt_secret_for_auth = jwt_secret.clone();
axum_middleware::from_fn(move |req, next| {
let secret = jwt_secret.clone();
let secret = jwt_secret_for_auth.clone();
let db = db.clone();
async move { jwt_auth_middleware_fn(secret, Some(db), req, next).await }
})
@@ -749,7 +750,8 @@ async fn main() -> anyhow::Result<()> {
let secret = secret_for_uploads.clone();
async move { upload_auth_middleware(secret, req, next).await }
}));
let fhir_routes = erp_health::HealthModule::fhir_routes().with_state(state.clone());
let fhir_routes = erp_health::HealthModule::fhir_routes_with_state(jwt_secret.clone())
.with_state(state.clone());
let app = Router::new()
.nest(
"/api/v1",

View File

@@ -112,6 +112,7 @@ impl FromRef<AppState> for erp_health::HealthState {
db: state.db.clone(),
event_bus: state.event_bus.clone(),
crypto: state.pii_crypto.clone(),
jwt_secret: state.config.jwt.secret.clone(),
}
}
}