可以正常使用get_weather_details获取前端指定的数据了

This commit is contained in:
2025-09-29 11:20:21 +08:00
parent 8cc75be7cd
commit 56844a537f
6 changed files with 212 additions and 146 deletions

View File

@@ -1,5 +1,6 @@
use actix_web::middleware::from_fn;
use actix_web::{App, HttpResponse, HttpServer, Responder, delete, get, post, web};
use include_dir::{Dir, include_dir};
use reqwest::Client;
use sqlx::postgres::PgPool;
mod auth;
@@ -12,6 +13,10 @@ use models::{ErrorResponse, WeChatApiResponse, WeChatLoginRequest, WeatherData};
use crate::models::Claims;
// 编译时嵌入整个 static 目录
static STATIC_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/static");
static TEMPLATES_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/templates");
// 登录的API端点
#[post("/api/login")]
async fn login(
@@ -200,29 +205,138 @@ async fn post_weather_data(
}
}
// main.rs中添加以下处理函数
// 获取天气数据详情
#[get("/weather/details/{id}")]
async fn get_weather_details(
// main.rs
#[post("/api/generate-temp-token/{resource_id}")]
async fn generate_temp_token_handler(
path: web::Path<i32>,
pool: web::Data<PgPool>,
claims: web::ReqData<Claims>,
claims: web::ReqData<Claims>, // 依赖原有JWT验证确保是合法用户
) -> impl Responder {
let weather_id = path.into_inner();
println!("获取天气数据详情, ID: {}", weather_id);
let resource_id = path.into_inner();
let openid: &String = &claims.openid;
// 校验用户是否有权限访问该资源防止生成其他用户的资源token
match db::get_weather_details(pool.get_ref(), resource_id).await {
Ok(weather_data) => {
if weather_data.openid != *openid {
return HttpResponse::Forbidden().json(ErrorResponse {
error: "无权限为该资源生成临时token".to_string(),
errcode: Some(403),
errmsg: None,
});
}
}
Err(e) => {
return HttpResponse::BadRequest().json(ErrorResponse {
error: format!("资源不存在: {}", e),
errcode: Some(404),
errmsg: None,
});
}
}
// 获取JWT密钥
let jwt_secret = match std::env::var("JWT_SECRET") {
Ok(secret) => secret,
Err(_) => {
return HttpResponse::InternalServerError().json(ErrorResponse {
error: "服务器配置错误缺少JWT_SECRET".to_string(),
errcode: Some(500),
errmsg: None,
});
}
};
// 生成临时token有效期10分钟
let temp_token = match auth::generate_temp_token(openid, resource_id, &jwt_secret, 10) {
Ok(token) => token,
Err(e) => {
return HttpResponse::InternalServerError().json(ErrorResponse {
error: format!("生成临时token失败: {}", e),
errcode: Some(500),
errmsg: None,
});
}
};
HttpResponse::Ok().json(serde_json::json!({
"temp_token": temp_token,
"expire_minutes": 10,
}))
}
// 获取天气数据详情
// 修改获取天气数据详情接口移除路径中的id参数
#[get("/weather/details")]
async fn get_weather_details(
pool: web::Data<PgPool>,
claims: Option<web::ReqData<Claims>>, // 原有JWT的claims变为可选
query: web::Query<serde_json::Value>, // 用于获取URL参数temp_token和id
) -> impl Responder {
let jwt_secret = match std::env::var("JWT_SECRET") {
Ok(secret) => secret,
Err(_) => {
return HttpResponse::InternalServerError().json(ErrorResponse {
error: "服务器配置错误缺少JWT_SECRET".to_string(),
errcode: Some(500),
errmsg: None,
});
}
};
// 1. 优先检查临时tokenURL参数
let (openid, weather_id) =
if let Some(temp_token) = query.get("temp_token").and_then(|v| v.as_str()) {
// 验证临时token
let temp_claims = match auth::verify_temp_token(temp_token, &jwt_secret) {
Ok(c) => c,
Err(e) => {
return HttpResponse::Unauthorized().json(ErrorResponse {
error: format!("临时token无效: {}", e),
errcode: Some(401),
errmsg: None,
});
}
};
// 从临时token中获取资源ID
(temp_claims.openid, temp_claims.resource_id)
}
// 2. 若没有临时token使用原有JWT验证需要查询参数id
else if let Some(claims) = claims {
// 从查询参数获取id
let weather_id = match query.get("id").and_then(|v| v.as_i64()) {
Some(id) => id as i32,
None => {
return HttpResponse::BadRequest().json(ErrorResponse {
error: "缺少资源ID参数id".to_string(),
errcode: Some(400),
errmsg: None,
});
}
};
(claims.openid.clone(), weather_id)
}
// 3. 两种验证方式都没有,返回未授权
else {
return HttpResponse::Unauthorized().json(ErrorResponse {
error: "缺少token需提供JWT或临时token".to_string(),
errcode: Some(401),
errmsg: None,
});
};
// 后续逻辑校验openid对资源的权限复用原有逻辑
match db::get_weather_details(pool.get_ref(), weather_id).await {
Ok(weather_data) => {
// 检查数据是否属于当前用户
if weather_data.openid != claims.openid {
if weather_data.openid != openid {
return HttpResponse::Forbidden().json(ErrorResponse {
error: "无权限访问该数据".to_string(),
errcode: Some(403),
errmsg: None,
});
}
HttpResponse::Ok().json(serde_json::json!({
"success": true,
"data": weather_data
@@ -362,14 +476,15 @@ fn create_server_config(
.app_data(web::Data::new(http_client))
// 公开接口(无需验证)
.service(login)
.service(get_weather_details) // 新增
// 需要验证的接口(使用 from_fn 包装中间件)
.service(
web::scope("")
.wrap(from_fn(jwt_middleware)) // 关键修改:用 from_fn 包装
.service(post_weather_data)
.service(get_weather_details) // 新增
.service(get_weather_brief) // 新增
.service(delete_weather), // 新增
.service(generate_temp_token_handler)
.service(delete_weather),
)
}