From 14c2ef25def1706251ef7a5635cf2bc8f5b1837f Mon Sep 17 00:00:00 2001 From: Milky0217 Date: Sun, 19 Apr 2026 17:34:35 +0800 Subject: [PATCH] =?UTF-8?q?fix(auth):=20/weather/details=20=E7=AB=AF?= =?UTF-8?q?=E7=82=B9=E8=87=AA=E5=B7=B1=E9=AA=8C=E8=AF=81=20JWT=EF=BC=88?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E9=9D=99=E9=BB=98=E5=88=B7=E6=96=B0=E5=90=8E?= =?UTF-8?q?=E4=BB=8D=20401=20=E9=97=AE=E9=A2=98=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:/weather/details 不在 jwt_middleware 保护范围内,导致即使前端发送 Authorization header,后端也不会验证 JWT。 修复:使用 HttpRequest 直接从 Authorization header 提取并验证 JWT,而非依赖 middleware 注入的 Claims。 验证:curl 测试确认 /weather/details?id=2 返回正确数据 --- src/handlers/weather.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/handlers/weather.rs b/src/handlers/weather.rs index 1944725..0f5e922 100644 --- a/src/handlers/weather.rs +++ b/src/handlers/weather.rs @@ -1,4 +1,4 @@ -use actix_web::{web, delete, get, post, HttpResponse}; +use actix_web::{web, delete, get, post, HttpRequest, HttpResponse}; use sqlx::postgres::PgPool; use tracing::{debug, info}; @@ -60,19 +60,28 @@ pub async fn generate_temp_token_handler( #[get("/weather/details")] pub async fn get_weather_details( pool: web::Data, - claims: Option>, + req: HttpRequest, query: web::Query, app_state: web::Data, ) -> Result { let mut is_temp_token = false; + // 从 Authorization header 中提取并验证 JWT(自己处理,不依赖 middleware) + let claims_from_header = || -> Option { + let auth_header = req.headers().get("Authorization")?; + let auth_str = auth_header.to_str().ok()?; + let token = auth_str.strip_prefix("Bearer ")?; + let jwt_secret = &app_state.jwt_secret; + auth::verify_token(token, jwt_secret).ok() + }; + let (openid, weather_id) = if let Some(temp_token) = query.get("temp_token").and_then(|v| v.as_str()) { is_temp_token = true; let temp_claims = auth::verify_temp_token(temp_token, &app_state.jwt_secret) .map_err(|e| AppError::Unauthorized(format!("临时token无效: {}", e)))?; (temp_claims.openid, temp_claims.resource_id) - } else if let Some(claims) = claims { + } else if let Some(claims) = claims_from_header() { let weather_id = match query.get("id") { Some(v) if v.is_i64() => v.as_i64().unwrap() as i32, Some(v) if v.is_string() => {