修改context,移除WhiteContext

This commit is contained in:
李运家 2024-09-30 18:01:20 +08:00
parent 7024a4f19d
commit d002c68fc2
8 changed files with 50 additions and 42 deletions

View File

@ -4,30 +4,28 @@ use domain::entities::account::Account;
#[derive(Debug, Clone)]
pub struct Context {
pub account: Arc<Account>,
pub token: Arc<String>,
pub account: Option<Arc<Account>>,
pub token: Option<Arc<String>>,
pub lang_tag: Arc<String>,
}
impl Context {
pub fn get_account(&self) -> &Account {
&self.account
}
pub fn get_token(&self) -> &String {
&self.token
}
pub fn get_lang_tag(&self) -> &String {
&self.account.lang_tag
pub fn get_account(&self) -> Option<Arc<Account>> {
if let Some(account) = &self.account {
return Some(account.clone());
} else {
None
}
}
#[derive(Debug, Clone)]
pub struct WhiteContext {
pub lang_tag: String,
pub fn get_token(&self) -> Option<Arc<String>> {
if let Some(token) = &self.token {
return Some(token.clone());
} else {
None
}
}
impl WhiteContext {
pub fn get_lang_tag(&self) -> &String {
&self.lang_tag
}

View File

@ -1,9 +1,11 @@
use std::sync::Arc;
use axum::{extract::Request, middleware::Next, response::{IntoResponse, Response}};
use http::{header, StatusCode};
use i18n::{message, message_ids::MessageId};
use jsonwebtoken::{decode, DecodingKey, Validation};
use crate::{cache::account_cache::LOGIN_CACHE, config, context::{Context, WhiteContext}, model::response::ResErr, token::Claims, utils::request_util};
use crate::{cache::account_cache::LOGIN_CACHE, config, context::Context, model::response::ResErr, token::Claims, utils::request_util};
const WHITE_LIST: &[(&str, &str)] = &[
("POST", "/account/sys"),
@ -12,9 +14,6 @@ const WHITE_LIST: &[(&str, &str)] = &[
/// 认证中间件包括网络请求白名单、token验证、登录缓存
pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
// 解析语言
let language = request_util::get_lang_tag(req.headers());
req.extensions_mut().insert(WhiteContext { lang_tag: language.clone() });
// 获取请求的url和method然后判断是否在白名单中如果在白名单中则直接返回next(req),否则继续执行下面的代码
let method = req.method().clone().to_string();
let mut uri = req.uri().path_and_query().unwrap().to_string();
@ -23,6 +22,9 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
if WHITE_LIST.into_iter().find(|item| {
return item.0 == method && item.1 == uri;
}).is_some() {
// 解析语言
let language = request_util::get_lang_tag(req.headers());
req.extensions_mut().insert(Context { lang_tag: Arc::new(language.clone()), account: None, token: None });
return next.run(req).await;
}
@ -33,12 +35,16 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
let parts: Vec<&str> = header_value.to_str().unwrap_or("").split_whitespace().collect();
if parts.len() != 2 || parts[0] != "Bearer" {
tracing::error!("无效的 authorization 请求头参数");
// 解析语言
let language = request_util::get_lang_tag(req.headers());
return ResErr::params(message!(&language, MessageId::BadRequest)).into_response();
}
parts[1]
},
None => {
tracing::error!("缺少 authorization 请求头参数");
// 解析语言
let language = request_util::get_lang_tag(req.headers());
return ResErr::auth(message!(&language, MessageId::BadRequest)).into_response()
},
};
@ -50,6 +56,8 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
let account = LOGIN_CACHE.get(&decoded.claims.sub).await;
if account.is_none() {
tracing::error!("无效的 token");
// 解析语言
let language = request_util::get_lang_tag(req.headers());
return ResErr::auth(message!(&language, MessageId::BadRequest)).into_response();
}
let account = account.unwrap();
@ -58,16 +66,20 @@ pub async fn authenticate_ctx(mut req: Request, next: Next) -> Response {
// if account.token != token {
// return (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response();
// }
let language = account.account.clone().lang_tag.clone();
// 将Claims附加到请求扩展中以便后续处理使用
req.extensions_mut().insert(
Context {
account: account.account.clone(),
token: account.token.clone()
account: Some(account.account.clone()),
token: Some(account.token.clone()),
lang_tag: Arc::new(language)
});
next.run(req).await
},
Err(_) => {
tracing::error!("无效的 token");
// 解析语言
let language = request_util::get_lang_tag(req.headers());
return ResErr::auth(message!(&language, MessageId::BadRequest)).into_response();
}
}

View File

@ -19,21 +19,19 @@ where
type Rejection = ResErr;
async fn from_request(req: http::Request<Body>, state: &S) -> Result<Self, Self::Rejection> {
// let context = req.extensions().get().unwrap();
let (parts, body) = req.into_parts();
let header = &parts.headers;
let query = Query::<T>::from_request(Request::from_parts(parts.clone(), body), state).await;
let lang_tag = request_util::get_lang_tag(header);
if let Ok(Query(data)) = query {
match data.validate() {
match super::validator::validate_params(&data, &lang_tag) {
Ok(_) => Ok(QueryValidator(data)),
Err(_) => {
let lang_tag = request_util::get_lang_tag(header);
let err = Err(ResErr::params(message!(&lang_tag, MessageId::InvalidParams)));
err
},
Err(err) => Err(err),
}
} else {
let lang_tag = request_util::get_lang_tag(header);
let err = Err(ResErr::params(message!(&lang_tag, MessageId::InvalidParams)));
err
}

View File

@ -1,4 +1,3 @@
use axum::extract::Request;
use http::{header, HeaderMap, HeaderValue};
/// 获取请求的语言

View File

@ -1,6 +1,6 @@
use axum::{Extension, Json};
use domain::{dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPassword, RefreshToken}, vo::account::{LoginAccount, RefreshTokenResult}};
use library::{context::{Context, WhiteContext}, model::{response::ResResult, validator}};
use library::{context::Context, model::{response::ResResult, validator}};
use crate::service;
@ -8,7 +8,7 @@ use crate::service;
///
/// google账号登录
pub async fn authenticate_google(
Extension(context): Extension<WhiteContext>,
Extension(context): Extension<Context>,
Json(req): Json<AuthenticateGooleAccountReq>
) -> ResResult<LoginAccount> {
validator::validate_params(&req, context.get_lang_tag())?;
@ -19,7 +19,7 @@ pub async fn authenticate_google(
///
/// 账号密码登录
pub async fn authenticate_with_password(
Extension(context): Extension<WhiteContext>,
Extension(context): Extension<Context>,
Json(req): Json<AuthenticateWithPassword>
) -> ResResult<LoginAccount> {
validator::validate_params(&req, context.get_lang_tag())?;

View File

@ -7,7 +7,7 @@ use domain::vo::account::{LoginAccount, RefreshTokenResult};
use i18n::message;
use i18n::message_ids::MessageId;
use library::cache::account_cache::{CacheAccount, LOGIN_CACHE};
use library::context::{Context, WhiteContext};
use library::context::Context;
use library::model::response::ResErr::ErrPerm;
use library::model::response::{ResErr, ResResult};
use library::social::google::GOOGLE_SOCIAL;
@ -15,7 +15,7 @@ use library::token::{generate_refresh_token, generate_token};
use library::{db, token};
pub async fn authenticate_google(
context: WhiteContext,
context: Context,
req: AuthenticateGooleAccountReq,
) -> ResResult<LoginAccount> {
let verify_result = GOOGLE_SOCIAL
@ -100,11 +100,12 @@ pub async fn refresh_token(
context: Context,
refresh_token: String,
) -> ResResult<RefreshTokenResult> {
let account = context.account.clone();
let lang = context.get_lang_tag();
let account = context.get_account().unwrap();
if token::verify_refresh_token(&refresh_token).is_err() {
return Err(ResErr::params(message!(
context.get_lang_tag(),
lang,
MessageId::InvalidToken
)));
}

View File

@ -11,7 +11,7 @@ pub async fn get_feedback_list_by_page(
page: i64,
page_size: i64,
) -> ResResult<FeedbackPageable> {
if !context.account.role.is_admin() {
if !context.account.unwrap().role.is_admin() {
tracing::error!("非管理员用户,无法获取反馈信息列表");
return Ok(FeedbackPageable::empty(page, page_size));
}
@ -41,7 +41,7 @@ async fn get_feedback_count() -> i64 {
/// 添加反馈信息
pub async fn add_feedback(context: Context, req: FeedbackAdd) -> ResResult<()> {
let account = context.account;
let account = context.account.unwrap();
let mut transaction = db!().begin().await?;
match Feedback::add_feedback(
&mut Feedback {

View File

@ -11,12 +11,12 @@ use i18n::{
message_ids::MessageId,
};
use library::{
cache::account_cache::{CacheAccount, LOGIN_CACHE}, context::WhiteContext, db, model::response::{ResErr, ResResult}, token::{generate_refresh_token, generate_token}
cache::account_cache::{CacheAccount, LOGIN_CACHE}, context::Context, db, model::response::{ResErr, ResResult}, token::{generate_refresh_token, generate_token}
};
/// 登录, 使用账号和密码
pub async fn authenticate_with_password(
context: WhiteContext,
context: Context,
req: AuthenticateWithPassword,
) -> ResResult<LoginAccount> {
let account =