如何向Axum处理器传递参数?JWT签名场景疑问
如何在Axum处理器中传递Server的公钥参数生成JWT令牌?
我正在构建一个提供并解码JWT令牌的简易服务器,目前遇到一处关键问题:Server结构体包含路由逻辑与配置项(其中公钥用于签名JWT令牌,使用jwt_simple库实现),但不知道如何将Server的公钥属性传递给auth处理器。
以下是我的代码:
pub struct Server { pub host: String, pub port: String, pub public_key: String, pub private_key: String } impl Server { pub async fn start(&self) { let routes = Router::new() .route("/", get(check)) .route("/auth", post(auth)); let hostport = format!("{}:{}", self.host, self.port); let addr: SocketAddr = hostport.parse().expect("invalid host:port pair"); axum::Server::bind(&addr) .serve(routes.into_make_service()) .await .unwrap(); } } async fn auth(Json(payload): Json<LoginInput>) -> impl IntoResponse { let token = RS384PublicKey::from_pem("id_like_to_put_Server::public_key_here") .sign(Claims::create(Duration::from_hours(1)))?; let lo = LoginOutput { token }; (StatusCode::OK, Json(lo)) }
解决方案:使用Axum的共享状态机制
Axum提供了Router::with_state方法传递共享配置,结合Arc实现多线程安全共享,具体步骤如下:
用
Arc包裹Server实例:
由于Axum服务器运行在多线程环境,Arc(原子引用计数)能保证状态安全跨线程共享,避免所有权冲突。修改
Server::start方法传递状态:
创建路由时,通过with_state把Arc<Server>传入路由上下文。在
auth处理器中提取状态:
使用Axum的State提取器获取共享的Server实例,从而访问其中的公钥。
修改后的完整代码:
use std::sync::Arc; use axum::{Router, extract::State, Json, http::StatusCode}; use jwt_simple::algorithms::RS384PublicKey; use jwt_simple::prelude::{Claims, Duration}; // 假设LoginInput和LoginOutput已定义 #[derive(serde::Deserialize)] pub struct LoginInput { // 登录字段示例:username, password } #[derive(serde::Serialize)] pub struct LoginOutput { token: String, } pub struct Server { pub host: String, pub port: String, pub public_key: String, pub private_key: String } impl Server { pub async fn start(self) { // 用Arc包裹Server实例,实现共享所有权 let state = Arc::new(self); let routes = Router::new() .route("/", get(check)) .route("/auth", post(auth)) .with_state(state); // 传入共享状态 let hostport = format!("{}:{}", state.host, state.port); let addr: std::net::SocketAddr = hostport.parse().expect("invalid host:port pair"); axum::Server::bind(&addr) .serve(routes.into_make_service()) .await .unwrap(); } } // 假设check处理器已定义 async fn check() -> &'static str { "OK" } async fn auth( // 提取共享的Server状态 State(server): State<Arc<Server>>, Json(payload): Json<LoginInput> ) -> Result<impl IntoResponse, Box<dyn std::error::Error>> { // 从Server实例中获取公钥并签名JWT let public_key = RS384PublicKey::from_pem(&server.public_key)?; let token = public_key.sign(Claims::create(Duration::from_hours(1)))?; let lo = LoginOutput { token }; Ok((StatusCode::OK, Json(lo))) }
关键说明:
Arc的作用:确保Server实例能在多个请求线程中安全共享,无需复制整个实例。State提取器:Axum会自动从路由上下文中匹配对应类型的状态,需保证处理器中的State<T>类型与with_state传入的类型完全一致。- 错误处理:原代码中的
?需要处理器返回Result类型,因此修改auth的返回值为Result<impl IntoResponse, Box<dyn Error>>,统一处理JWT签名和公钥解析的错误。
内容的提问来源于stack exchange,提问作者Francesco
相关产品推荐
相关产品推荐

