chuanyue-service/library/src/middleware/req_ctx.rs
2024-06-21 14:28:19 +08:00

72 lines
3.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use axum::{extract::Request, middleware::Next, response::{IntoResponse, Response}};
use http::{header, StatusCode};
use jsonwebtoken::{decode, DecodingKey, Validation};
use crate::{cache::account_cache::LOGIN_CACHE, config, context::{Context, WhiteContext}, token::Claims};
const WHITE_LIST: &[(&str, &str)] = &[
("POST", "/account/sys"),
];
pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
// 获取请求的url和method然后判断是否在白名单中如果在白名单中则直接返回next(req),否则继续执行下面的代码
let method = req.method().clone().to_string();
let uri = req.uri().path_and_query().unwrap().to_string();
if WHITE_LIST.into_iter().find(|item| {
return item.0 == method && item.1 == uri;
}).is_some() {
// 解析语言
let language_header = req.headers().get(header::ACCEPT_LANGUAGE);
let language = match language_header {
Some(value) => {
let value_str: Vec<&str> = value.to_str().unwrap_or("zh-CN").split(',').collect();
if value_str.is_empty() {
String::from("zh-CN")
} else {
String::from(value_str[0])
}
},
None => String::from("zh-CN"),
};
req.extensions_mut().insert(WhiteContext { lang_tag: language });
return next.run(req).await;
}
// 解析token
let auth_header = req.headers().get(header::AUTHORIZATION);
let token = match auth_header {
Some(header_value) => {
let parts: Vec<&str> = header_value.to_str().unwrap_or("").split_whitespace().collect();
if parts.len() != 2 || parts[0] != "Bearer" {
return (StatusCode::BAD_REQUEST, "Invalid authorization header format".to_string()).into_response();
}
parts[1]
},
None => return (StatusCode::UNAUTHORIZED, "Missing authorization header".to_string()).into_response(),
};
let validation = Validation::default();
match decode::<Claims>(token, &DecodingKey::from_secret(config!().jwt.token_secret.as_bytes()), &validation) {
Ok(decoded) => {
// 从缓存中获取当前用户信息
let account = LOGIN_CACHE.get(&decoded.claims.sub).await;
if account.is_none() {
return (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response();
}
let account = account.unwrap();
// 判断token是否有效(注释掉,如果服务因为升级等原因手动重启了,缓存的数据也不再存在)
// let account = account.unwrap();
// if account.token != token {
// return (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response();
// }
// 将Claims附加到请求扩展中以便后续处理使用
req.extensions_mut().insert(
Context {
account: account.account.clone(),
token: account.token.clone()
});
next.run(req).await
},
Err(_) => (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(),
}
}