增加网络请求上下文

This commit is contained in:
李运家 2024-06-13 18:06:11 +08:00
parent 6572f48696
commit a7eec7882e
8 changed files with 53 additions and 14 deletions

View File

@ -1,6 +1,6 @@
use axum::{Extension, Json};
use domain::{dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPassword, RefreshToken}, vo::account::{LoginAccount, RefreshTokenResult}};
use library::{cache::account_cache::CacheAccount, res::{response::{ ResData, ResResult}, validator}};
use library::{context::Context, res::{response::{ ResData, ResResult}, validator}};
pub async fn authenticate_google(
Json(req): Json<AuthenticateGooleAccountReq>
@ -17,10 +17,10 @@ pub async fn authenticate_with_password(
}
pub async fn refresh_token(
Extension(account): Extension<CacheAccount>,
Extension(context): Extension<Context>,
Json(refresh_token): Json<RefreshToken>
) -> ResResult<ResData<RefreshTokenResult>> {
tracing::debug!("刷新token, {:?}", account);
tracing::debug!("刷新token, {:?}", context);
validator::validate_params(&refresh_token, "")?;
service::account::refresh_token(account, refresh_token.token).await
service::account::refresh_token(context, refresh_token.token).await
}

View File

@ -27,7 +27,7 @@ pub(crate) fn init() -> Router {
.get(controller::feedback::get_feedback_list_by_page),
)
.layer(axum::middleware::from_fn(
library::middleware::req_token::authenticate_access_token,
library::middleware::req_ctx::authenticate_ctx,
));
Router::new()

23
library/src/context.rs Normal file
View File

@ -0,0 +1,23 @@
use domain::entities::account::Account;
#[derive(Debug, Clone)]
pub struct Context {
pub account: Account,
pub local: String,
pub token: String,
}
impl Context {
pub fn get_account(&self) -> &Account {
&self.account
}
pub fn get_token(&self) -> &String {
&self.token
}
pub fn get_local(&self) -> &String {
&self.local
}
}

View File

@ -6,3 +6,4 @@ pub mod middleware;
pub mod token;
pub mod social;
pub mod cache;
pub mod context;

View File

@ -1,4 +1,4 @@
pub mod req_id;
pub mod req_log;
pub mod cors;
pub mod req_token;
pub mod req_ctx;

View File

@ -2,7 +2,7 @@ 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, token::Claims};
use crate::{cache::account_cache::LOGIN_CACHE, config, context::Context, token::Claims};
const WHITE_LIST: &[(&str, &str)] = &[
("GET", "/api/v1/users/:id"),
@ -11,7 +11,7 @@ const WHITE_LIST: &[(&str, &str)] = &[
("POST", "/account/sys"),
];
pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response {
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();
@ -21,6 +21,7 @@ pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response
return next.run(req).await;
}
// 解析token
let auth_header = req.headers().get(header::AUTHORIZATION);
let token = match auth_header {
Some(header_value) => {
@ -33,6 +34,20 @@ pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response
None => return (StatusCode::UNAUTHORIZED, "Missing authorization header".to_string()).into_response(),
};
// 解析语言
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[1])
}
},
None => String::from("zh-CN"),
};
let validation = Validation::default();
match decode::<Claims>(token, &DecodingKey::from_secret(config!().jwt.token_secret.as_bytes()), &validation) {
Ok(decoded) => {
@ -41,13 +56,14 @@ pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response
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(account.unwrap());
req.extensions_mut().insert(Context { account: account.account, local: language, token: account.token });
next.run(req).await
},
Err(_) => (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(),

View File

@ -1,5 +1,3 @@
use std::borrow::Cow;
use validator::Validate;
use super::response::{ResData, ResErr, ResResult};

View File

@ -3,6 +3,7 @@ use domain::dto::account::AuthenticateGooleAccountReq;
use domain::entities::account::Account;
use domain::vo::account::{LoginAccount, RefreshTokenResult};
use library::cache::account_cache::{CacheAccount, LOGIN_CACHE};
use library::context::Context;
use library::res::response::ResErr::ErrPerm;
use library::res::response::{ResData, ResErr, ResResult};
use library::social::google::GOOGLE_SOCIAL;
@ -74,10 +75,10 @@ pub async fn authenticate_google(
}
pub async fn refresh_token(
cache_account: CacheAccount,
context: Context,
refresh_token: String,
) -> ResResult<ResData<RefreshTokenResult>> {
let account = cache_account.account;
let account = context.account;
if token::verify_refresh_token(&refresh_token).is_err() {
return Err(ResErr::params("refresh_token无效"));