From 6f0c0e5f96828e791ae4056d13851b0ba5dbb022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=BF=90=E5=AE=B6?= Date: Thu, 6 Jun 2024 17:56:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0token=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/controller/account.rs | 16 ++++++--- api/src/router.rs | 4 +++ domain/src/dto/account.rs | 5 +++ domain/src/vo/account.rs | 8 ++++- library/src/middleware/req_token.rs | 2 +- service/src/account.rs | 52 +++++++++++++++++++++++------ 6 files changed, 70 insertions(+), 17 deletions(-) diff --git a/api/src/controller/account.rs b/api/src/controller/account.rs index 7e67823..e848551 100644 --- a/api/src/controller/account.rs +++ b/api/src/controller/account.rs @@ -1,6 +1,6 @@ -use axum::Json; -use domain::{dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPassword}, vo::account::LoginAccount}; -use library::resp::response::{ ResData, ResResult}; +use axum::{Extension, Json}; +use domain::{dto::account::{AuthenticateGooleAccountReq, AuthenticateWithPassword, RefreshToken}, vo::account::{LoginAccount, RefreshTokenResult}}; +use library::{cache::account_cache::CacheAccount, resp::response::{ ResData, ResResult}}; use validator::Validate; pub async fn authenticate_google( @@ -17,4 +17,12 @@ pub async fn authenticate_with_password( req.validate()?; service::sys_account::authenticate_with_password(req).await -} \ No newline at end of file +} + +pub async fn refresh_token( + Extension(account): Extension, + Json(refresh_token): Json +) -> ResResult> { + tracing::debug!("刷新token, {:?}", account); + service::account::refresh_token(account, refresh_token.token).await +} diff --git a/api/src/router.rs b/api/src/router.rs index 9f13c77..459b754 100644 --- a/api/src/router.rs +++ b/api/src/router.rs @@ -17,6 +17,10 @@ pub(crate) fn init() -> Router { "/account/sys", post(controller::account::authenticate_with_password), ) + .route( + "/account/refresh-token", + post(controller::account::refresh_token) + ) .route( "/feedback", post(controller::feedback::add_feedback) diff --git a/domain/src/dto/account.rs b/domain/src/dto/account.rs index 0d3c841..73d80a6 100644 --- a/domain/src/dto/account.rs +++ b/domain/src/dto/account.rs @@ -14,3 +14,8 @@ pub struct AuthenticateGooleAccountReq { #[validate(required(message = "用户ID Token不能为空"), length(min = 1, message = "用户ID Token不能为空"))] pub id_token: Option, } + +#[derive(Debug, Validate, Deserialize, Serialize)] +pub struct RefreshToken { + pub token: String, +} diff --git a/domain/src/vo/account.rs b/domain/src/vo/account.rs index 705bd52..52bf89d 100644 --- a/domain/src/vo/account.rs +++ b/domain/src/vo/account.rs @@ -14,4 +14,10 @@ pub struct LoginAccount { pub email: Option, pub token: String, pub refresh_token: String, -} \ No newline at end of file +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct RefreshTokenResult { + pub token: String, + pub refresh_token: String, +} diff --git a/library/src/middleware/req_token.rs b/library/src/middleware/req_token.rs index 0f5132a..fecac49 100644 --- a/library/src/middleware/req_token.rs +++ b/library/src/middleware/req_token.rs @@ -47,7 +47,7 @@ pub async fn authenticate_access_token(mut req: Request, next: Next) -> Response // return (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(); // } // 将Claims附加到请求扩展中,以便后续处理使用 - req.extensions_mut().insert(account); + req.extensions_mut().insert(account.unwrap()); next.run(req).await }, Err(_) => (StatusCode::UNAUTHORIZED, "Invalid token".to_string()).into_response(), diff --git a/service/src/account.rs b/service/src/account.rs index b77b319..6ad658c 100644 --- a/service/src/account.rs +++ b/service/src/account.rs @@ -1,11 +1,12 @@ use chrono::Utc; use domain::dto::account::AuthenticateGooleAccountReq; use domain::entities::account::Account; -use domain::vo::account::LoginAccount; +use domain::vo::account::{LoginAccount, RefreshTokenResult}; use library::cache::account_cache::{CacheAccount, LOGIN_CACHE}; use library::resp::response::ResErr::ErrPerm; -use library::resp::response::{ResErr, ResData, ResResult}; +use library::resp::response::{ResData, ResErr, ResResult}; use library::social::google::GOOGLE_SOCIAL; +use library::token::{generate_refresh_token, generate_token}; use library::{db, token}; pub async fn authenticate_google( @@ -59,15 +60,44 @@ pub async fn authenticate_google( ) .await; - let login_account = LoginAccount{ - username: account.username, - display_name: account.display_name, - avatar_url: account.avatar_url, - metadata: account.metadata, - wallet: account.wallet, - email: account.email, - token, - refresh_token + let login_account = LoginAccount { + username: account.username, + display_name: account.display_name, + avatar_url: account.avatar_url, + metadata: account.metadata, + wallet: account.wallet, + email: account.email, + token, + refresh_token, }; return Ok(ResData::some(login_account)); } + +pub async fn refresh_token( + cache_account: CacheAccount, + refresh_token: String, +) -> ResResult> { + let account = cache_account.account; + + if token::verify_refresh_token(&refresh_token).is_err() { + return Err(ResErr::params("refresh_token无效")); + } + + let refresh_token = RefreshTokenResult { + token: generate_token(&account.id), + refresh_token: generate_refresh_token(&account.id), + }; + + LOGIN_CACHE.remove(&account.id).await; + LOGIN_CACHE + .insert( + account.id.to_owned(), + CacheAccount { + account: account.clone(), + token: refresh_token.token.to_owned(), + }, + ) + .await; + + Ok(ResData::some(refresh_token)) +}