可以在使用temp_token的情况下使浏览器和微信小程序前端都能获取到正确的数据
This commit is contained in:
52
Cargo.lock
generated
52
Cargo.lock
generated
@@ -19,6 +19,29 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "actix-files"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c0d87f10d70e2948ad40e8edea79c8e77c6c66e0250a4c1f09b690465199576"
|
||||||
|
dependencies = [
|
||||||
|
"actix-http",
|
||||||
|
"actix-service",
|
||||||
|
"actix-utils",
|
||||||
|
"actix-web",
|
||||||
|
"bitflags",
|
||||||
|
"bytes",
|
||||||
|
"derive_more",
|
||||||
|
"futures-core",
|
||||||
|
"http-range",
|
||||||
|
"log",
|
||||||
|
"mime",
|
||||||
|
"mime_guess",
|
||||||
|
"percent-encoding",
|
||||||
|
"pin-project-lite",
|
||||||
|
"v_htmlescape",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "actix-http"
|
name = "actix-http"
|
||||||
version = "3.11.1"
|
version = "3.11.1"
|
||||||
@@ -952,6 +975,12 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "http-range"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "httparse"
|
name = "httparse"
|
||||||
version = "1.10.1"
|
version = "1.10.1"
|
||||||
@@ -1393,6 +1422,16 @@ version = "0.3.17"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "2.0.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
|
||||||
|
dependencies = [
|
||||||
|
"mime",
|
||||||
|
"unicase",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.8.9"
|
version = "0.8.9"
|
||||||
@@ -1875,6 +1914,7 @@ dependencies = [
|
|||||||
name = "rust-backend"
|
name = "rust-backend"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"actix-files",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenvy",
|
"dotenvy",
|
||||||
@@ -2672,6 +2712,12 @@ version = "1.18.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "2.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.18"
|
version = "0.3.18"
|
||||||
@@ -2739,6 +2785,12 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "v_htmlescape"
|
||||||
|
version = "0.15.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vcpkg"
|
name = "vcpkg"
|
||||||
version = "0.2.15"
|
version = "0.2.15"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
actix-files = "0.6.8"
|
||||||
actix-web = "4.11.0"
|
actix-web = "4.11.0"
|
||||||
chrono = {version = "0.4.41", features=["serde"]}
|
chrono = {version = "0.4.41", features=["serde"]}
|
||||||
dotenvy = "0.15.7"
|
dotenvy = "0.15.7"
|
||||||
|
|||||||
102
src/main.rs
102
src/main.rs
@@ -266,12 +266,11 @@ async fn generate_temp_token_handler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取天气数据详情
|
// 获取天气数据详情
|
||||||
// 修改获取天气数据详情接口(移除路径中的id参数)
|
|
||||||
#[get("/weather/details")]
|
#[get("/weather/details")]
|
||||||
async fn get_weather_details(
|
async fn get_weather_details(
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
claims: Option<web::ReqData<Claims>>, // 原有JWT的claims变为可选
|
claims: Option<web::ReqData<Claims>>,
|
||||||
query: web::Query<serde_json::Value>, // 用于获取URL参数temp_token和id
|
query: web::Query<serde_json::Value>,
|
||||||
) -> impl Responder {
|
) -> impl Responder {
|
||||||
let jwt_secret = match std::env::var("JWT_SECRET") {
|
let jwt_secret = match std::env::var("JWT_SECRET") {
|
||||||
Ok(secret) => secret,
|
Ok(secret) => secret,
|
||||||
@@ -284,9 +283,12 @@ async fn get_weather_details(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 标记是否使用临时token
|
||||||
|
let mut is_temp_token = false;
|
||||||
// 1. 优先检查临时token(URL参数)
|
// 1. 优先检查临时token(URL参数)
|
||||||
let (openid, weather_id) =
|
let (openid, weather_id) =
|
||||||
if let Some(temp_token) = query.get("temp_token").and_then(|v| v.as_str()) {
|
if let Some(temp_token) = query.get("temp_token").and_then(|v| v.as_str()) {
|
||||||
|
is_temp_token = true; // 标记为临时token访问
|
||||||
// 验证临时token
|
// 验证临时token
|
||||||
let temp_claims = match auth::verify_temp_token(temp_token, &jwt_secret) {
|
let temp_claims = match auth::verify_temp_token(temp_token, &jwt_secret) {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
@@ -327,20 +329,17 @@ async fn get_weather_details(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 后续逻辑:校验openid对资源的权限(复用原有逻辑)
|
// 获取天气数据
|
||||||
match db::get_weather_details(pool.get_ref(), weather_id).await {
|
let weather_data = match db::get_weather_details(pool.get_ref(), weather_id).await {
|
||||||
Ok(weather_data) => {
|
Ok(data) => {
|
||||||
if weather_data.openid != openid {
|
if data.openid != openid {
|
||||||
return HttpResponse::Forbidden().json(ErrorResponse {
|
return HttpResponse::Forbidden().json(ErrorResponse {
|
||||||
error: "无权限访问该数据".to_string(),
|
error: "无权限访问该数据".to_string(),
|
||||||
errcode: Some(403),
|
errcode: Some(403),
|
||||||
errmsg: None,
|
errmsg: None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
HttpResponse::Ok().json(serde_json::json!({
|
data
|
||||||
"success": true,
|
|
||||||
"data": weather_data
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
Err(error_msg) => {
|
Err(error_msg) => {
|
||||||
eprintln!("获取天气数据详情失败: {}", error_msg);
|
eprintln!("获取天气数据详情失败: {}", error_msg);
|
||||||
@@ -349,12 +348,59 @@ async fn get_weather_details(
|
|||||||
} else {
|
} else {
|
||||||
500
|
500
|
||||||
};
|
};
|
||||||
HttpResponse::Ok().json(serde_json::json!({
|
return HttpResponse::Ok().json(serde_json::json!({
|
||||||
"success": false,
|
"success": false,
|
||||||
"errcode": errcode,
|
"errcode": errcode,
|
||||||
"errmsg": error_msg
|
"errmsg": error_msg
|
||||||
}))
|
}));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
// 根据访问方式返回不同格式
|
||||||
|
if is_temp_token {
|
||||||
|
// 临时token访问:返回HTML页面,数据交由前端afterbody.js渲染
|
||||||
|
// 读取模板文件
|
||||||
|
let index_html = match TEMPLATES_DIR.get_file("index.html") {
|
||||||
|
Some(file) => file.contents_utf8().unwrap_or_default(),
|
||||||
|
None => {
|
||||||
|
return HttpResponse::InternalServerError().json(ErrorResponse {
|
||||||
|
error: "无法找到模板文件".to_string(),
|
||||||
|
errcode: Some(500),
|
||||||
|
errmsg: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 将天气数据序列化为JSON字符串,供前端JS使用
|
||||||
|
let weather_data_json = serde_json::to_string(&weather_data).unwrap_or_default();
|
||||||
|
|
||||||
|
// 生成数据注入脚本:将数据挂载到window对象,供afterbody.js访问
|
||||||
|
let data_script = format!(
|
||||||
|
r#"
|
||||||
|
<script>
|
||||||
|
// 注入后端数据供前端渲染使用
|
||||||
|
window.weatherData = {};
|
||||||
|
</script>
|
||||||
|
"#,
|
||||||
|
weather_data_json
|
||||||
|
);
|
||||||
|
|
||||||
|
// 将数据脚本插入到模板中,同时显示详细信息容器
|
||||||
|
let rendered_html = index_html
|
||||||
|
.replace("<!-- 详细信息将在这里显示 -->", &data_script)
|
||||||
|
.replace(
|
||||||
|
"style=\"display: none;\"",
|
||||||
|
"", // 显示详细信息容器,供前端渲染内容
|
||||||
|
);
|
||||||
|
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.content_type("text/html; charset=utf-8")
|
||||||
|
.body(rendered_html)
|
||||||
|
} else {
|
||||||
|
// JWT访问:返回JSON数据
|
||||||
|
HttpResponse::Ok().json(serde_json::json!({
|
||||||
|
"success": true,
|
||||||
|
"data": weather_data
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +504,34 @@ async fn delete_weather(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 在 main.rs 中添加以下函数,用于处理静态文件请求
|
||||||
|
async fn serve_static_files(path: web::Path<String>) -> impl Responder {
|
||||||
|
// 获取请求的文件路径(例如 "css/style.css")
|
||||||
|
let file_path = path.into_inner();
|
||||||
|
|
||||||
|
// 从嵌入的 STATIC_DIR 中查找文件
|
||||||
|
match STATIC_DIR.get_file(&file_path) {
|
||||||
|
Some(file) => {
|
||||||
|
// 根据文件扩展名设置 Content-Type
|
||||||
|
let content_type = match file_path.split('.').last() {
|
||||||
|
Some("css") => "text/css",
|
||||||
|
Some("js") => "application/javascript",
|
||||||
|
Some("html") => "text/html",
|
||||||
|
Some("ttf") | Some("woff") | Some("woff2") => "font/woff2", // 字体文件
|
||||||
|
_ => "application/octet-stream", // 默认类型
|
||||||
|
};
|
||||||
|
|
||||||
|
HttpResponse::Ok()
|
||||||
|
.content_type(content_type)
|
||||||
|
.body(file.contents())
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
// 文件不存在时返回 404
|
||||||
|
HttpResponse::NotFound().body("静态文件不存在")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 创建服务器配置的函数
|
// 创建服务器配置的函数
|
||||||
fn create_server_config(
|
fn create_server_config(
|
||||||
pool: PgPool,
|
pool: PgPool,
|
||||||
@@ -475,6 +549,8 @@ fn create_server_config(
|
|||||||
.app_data(web::Data::new(pool))
|
.app_data(web::Data::new(pool))
|
||||||
.app_data(web::Data::new(http_client))
|
.app_data(web::Data::new(http_client))
|
||||||
// 公开接口(无需验证)
|
// 公开接口(无需验证)
|
||||||
|
// 注册静态文件服务:处理 /static/* 路径的请求
|
||||||
|
.service(web::resource("/static/{tail:.*}").route(web::get().to(serve_static_files)))
|
||||||
.service(login)
|
.service(login)
|
||||||
.service(get_weather_details) // 新增
|
.service(get_weather_details) // 新增
|
||||||
// 需要验证的接口(使用 from_fn 包装中间件)
|
// 需要验证的接口(使用 from_fn 包装中间件)
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
if (versionElement) {
|
if (versionElement) {
|
||||||
versionElement.textContent = `版本号: ${version}`;
|
versionElement.textContent = `版本号: ${version}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log(window.weatherData)
|
||||||
});
|
});
|
||||||
|
|
||||||
// 下载按钮
|
// 下载按钮
|
||||||
@@ -365,10 +367,6 @@ document.getElementById('downloadBtn').addEventListener('click', function() {
|
|||||||
}, 2000); // 假设下载需要2秒完成,你可以根据实际情况调整
|
}, 2000); // 假设下载需要2秒完成,你可以根据实际情况调整
|
||||||
});
|
});
|
||||||
|
|
||||||
// 获取记录内容
|
|
||||||
document.getElementById('viewDetailsBtn').addEventListener('click', function() {
|
|
||||||
});
|
|
||||||
|
|
||||||
// 工具函数
|
// 工具函数
|
||||||
|
|
||||||
// 函数用于将日期格式化为 xxxx-xx-xx 形式
|
// 函数用于将日期格式化为 xxxx-xx-xx 形式
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>KaTeX示例</title>
|
<title>KaTeX示例</title>
|
||||||
<link rel="stylesheet" href="../static/css/katex.min.css" crossorigin="anonymous">
|
<link rel="stylesheet" href="/static/css/katex.min.css" crossorigin="anonymous">
|
||||||
<script defer src="../static/js/katex.min.js" crossorigin="anonymous"></script>
|
<script defer src="/static/js/katex.min.js" crossorigin="anonymous"></script>
|
||||||
<script defer src="../static/js/auto-render.min.js" crossorigin="anonymous"></script>
|
<script defer src="/static/js/auto-render.min.js" crossorigin="anonymous"></script>
|
||||||
<script src="../static/js/html2pdf.bundle.min.js"></script>
|
<script src="/static/js/html2pdf.bundle.min.js"></script>
|
||||||
<link rel="stylesheet" href="../static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
|
|
||||||
<div class="notification" id="notification"></div>
|
<div class="notification" id="notification"></div>
|
||||||
|
|
||||||
<script src="../static/js/afterbody.js"></script>
|
<script src="/static/js/afterbody.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
|
|||||||
Reference in New Issue
Block a user