Rust + Axum 中间件:JWT 鉴权与请求上下文注入
test12026-09-110 次阅读
把鉴权从每个 handler 里抽出来
在 Axum 里,如果每一个路由处理函数都自己解析 token、校验签名、再取用户 ID,重复代码会迅速失控。更干净的做法是用中间件(middleware):在请求进入业务 handler 之前统一完成鉴权,并把解析出的用户身份写进请求扩展(extensions),后续 handler 直接用 extractor 取,不需要再碰 HTTP 头。
中间件本身就是一个异步函数
Axum 的中间件签名很直白:拿到 Request、Next,处理完调用 next.run 继续链路。下面从 Authorization 头取出 Bearer token,用 jsonwebtoken 解码,失败直接返回 401。
use axum::{
extract::Request,
middleware::Next,
response::Response,
http::{StatusCode, HeaderMap},
};
use jsonwebtoken::{decode, DecodingKey, Validation};
use serde::Deserialize;
#[derive(Debug, Deserialize)]
struct Claims {
sub: String,
exp: usize,
}
pub async fn auth_middleware(
headers: HeaderMap,
mut req: Request,
next: Next,
) -> Result<Response, StatusCode> {
let token = headers
.get("authorization")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.strip_prefix("Bearer "))
.ok_or(StatusCode::UNAUTHORIZED)?;
let data = decode::<Claims>(
token,
&DecodingKey::from_secret(b"secret"),
&Validation::default(),
)
.map_err(|_| StatusCode::UNAUTHORIZED)?;
req.extensions_mut().insert(data.claims.sub);
Ok(next.run(req).await)
}
业务 handler 直接取身份
解析出的 sub 已经放进 extensions,handler 用 FromRequestParts 取回来即可。注意中间件写入的类型必须和 extractor 的类型一致,否则取不到。
use axum::extract::State;
use axum::response::IntoResponse;
async fn me(State(pool): State<Db>, sub: UserId) -> impl IntoResponse {
let id = sub.0;
format!("hello user {id}")
}
// 用一个新类型包裹 String,避免和别的 String extractor 冲突
struct UserId(pub String);
impl axum::extract::FromRequestParts<()> for UserId {
type Rejection = StatusCode;
async fn from_request_parts(
parts: &mut axum::http::request::Parts,
_: &(),
) -> Result<Self, Self::Rejection> {
parts
.extensions
.get::<String>()
.map(|s| UserId(s.clone()))
.ok_or(StatusCode::UNAUTHORIZED)
}
}
把中间件挂到路由上
let app = Router::new()
.route("/me", get(me))
.route_layer(middleware::from_fn(auth_middleware));
route_layer 只保护它后面的路由,公开接口和受保护接口可以分层挂载,互不影响。中间件不持有状态、可测试、可组合,是 Axum 里处理鉴权、日志、限流这类横切逻辑的标准位置。
T
test1
文章作者
把鉴权从每个 handler 里抽出来 在 Axum 里,如果每一个路由处理函数都自己解析 token、校验签名、再取...
- 分类
- 技术
- 发布时间
- 2026-09-11
- 字数
- 约 2200 字
- 阅读
- 0 次
