fix(server): Rate limit fail-close 改为环境变量控制
开发环境默认 fail-open(Redis 不可达时放行), 生产环境设置 ERP__RATE_LIMIT__FAIL_CLOSE=true 启用 fail-close(返回 503)。
This commit is contained in:
@@ -180,14 +180,22 @@ pub async fn account_lockout_middleware(
|
|||||||
) -> Response {
|
) -> Response {
|
||||||
let avail = redis_avail();
|
let avail = redis_avail();
|
||||||
|
|
||||||
// Redis 不可达时 fail-close:拒绝登录请求(安全优先)
|
// Redis 可达性检查:生产环境 fail-close,开发环境 fail-open(通过环境变量控制)
|
||||||
|
let fail_close = std::env::var("ERP__RATE_LIMIT__FAIL_CLOSE")
|
||||||
|
.map(|v| v == "true" || v == "1")
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !avail.should_try().await {
|
if !avail.should_try().await {
|
||||||
|
if fail_close {
|
||||||
tracing::error!("Redis 不可达,fail-close 拒绝登录请求");
|
tracing::error!("Redis 不可达,fail-close 拒绝登录请求");
|
||||||
return (StatusCode::SERVICE_UNAVAILABLE, axum::Json(RateLimitResponse {
|
return (StatusCode::SERVICE_UNAVAILABLE, axum::Json(RateLimitResponse {
|
||||||
error: "service_unavailable".to_string(),
|
error: "service_unavailable".to_string(),
|
||||||
message: "安全服务暂不可用,请稍后重试".to_string(),
|
message: "安全服务暂不可用,请稍后重试".to_string(),
|
||||||
})).into_response();
|
})).into_response();
|
||||||
}
|
}
|
||||||
|
tracing::error!("Redis 不可达,fail-open 放行(非生产模式,建议设置 ERP__RATE_LIMIT__FAIL_CLOSE=true)");
|
||||||
|
return next.run(req).await;
|
||||||
|
}
|
||||||
|
|
||||||
// 获取 Redis 连接
|
// 获取 Redis 连接
|
||||||
let mut conn = match state.redis.get_multiplexed_async_connection().await {
|
let mut conn = match state.redis.get_multiplexed_async_connection().await {
|
||||||
@@ -196,13 +204,17 @@ pub async fn account_lockout_middleware(
|
|||||||
c
|
c
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!(error = %e, "Redis 连接失败,fail-close 拒绝登录请求");
|
|
||||||
avail.mark_failed().await;
|
avail.mark_failed().await;
|
||||||
|
if fail_close {
|
||||||
|
tracing::error!(error = %e, "Redis 连接失败,fail-close 拒绝登录请求");
|
||||||
return (StatusCode::SERVICE_UNAVAILABLE, axum::Json(RateLimitResponse {
|
return (StatusCode::SERVICE_UNAVAILABLE, axum::Json(RateLimitResponse {
|
||||||
error: "service_unavailable".to_string(),
|
error: "service_unavailable".to_string(),
|
||||||
message: "安全服务暂不可用,请稍后重试".to_string(),
|
message: "安全服务暂不可用,请稍后重试".to_string(),
|
||||||
})).into_response();
|
})).into_response();
|
||||||
}
|
}
|
||||||
|
tracing::error!(error = %e, "Redis 连接失败,fail-open 放行(非生产模式)");
|
||||||
|
return next.run(req).await;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 读取请求体以提取 username
|
// 读取请求体以提取 username
|
||||||
|
|||||||
Reference in New Issue
Block a user