跳到主要内容

认证与授权

问题

Rust Web 应用如何实现认证和授权?

答案

JWT 认证(最常用)

use axum::{
extract::Request,
http::StatusCode,
middleware::Next,
response::Response,
};
use jsonwebtoken::{decode, encode, Header, Validation, EncodingKey, DecodingKey};
use serde::{Deserialize, Serialize};
use chrono::Utc;

#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String, // 用户 ID
role: String, // 角色
exp: usize, // 过期时间
}

// 生成 Token
fn create_token(user_id: &str, role: &str, secret: &[u8]) -> String {
let claims = Claims {
sub: user_id.to_string(),
role: role.to_string(),
exp: (Utc::now() + chrono::Duration::hours(24)).timestamp() as usize,
};
encode(&Header::default(), &claims, &EncodingKey::from_secret(secret)).unwrap()
}

// JWT 认证中间件
async fn jwt_auth(
mut req: Request,
next: Next,
) -> Result<Response, StatusCode> {
let secret = b"your-secret-key"; // 实际应从配置读取

let token = req
.headers()
.get("Authorization")
.and_then(|v| v.to_str().ok())
.and_then(|v| v.strip_prefix("Bearer "))
.ok_or(StatusCode::UNAUTHORIZED)?;

let claims = decode::<Claims>(
token,
&DecodingKey::from_secret(secret),
&Validation::default(),
)
.map_err(|_| StatusCode::UNAUTHORIZED)?
.claims;

// 将用户信息注入请求
req.extensions_mut().insert(claims);

Ok(next.run(req).await)
}

基于角色的授权(RBAC)

use axum::extract::Extension;

// 角色检查中间件工厂
fn require_role(role: &'static str) -> impl Fn(Request, Next) -> _ + Clone {
move |req: Request, next: Next| {
let role = role;
async move {
let claims = req.extensions().get::<Claims>()
.ok_or(StatusCode::UNAUTHORIZED)?;

if claims.role != role {
return Err(StatusCode::FORBIDDEN);
}

Ok::<_, StatusCode>(next.run(req).await)
}
}
}

// 使用
let app = Router::new()
.route("/admin", get(admin_handler))
.layer(middleware::from_fn(require_role("admin")))
.layer(middleware::from_fn(jwt_auth));

常见面试问题

Q1: JWT Secret 应该如何管理?

答案

  • 不要硬编码:通过环境变量或配置中心加载
  • 使用足够强的密钥:至少 256 位(32 字节)随机字节
  • 考虑使用 RS256:非对称加密,公钥验证、私钥签发
  • Token 刷新:Access Token 短期有效(15 分钟),Refresh Token 长期有效

Q2: 除了 JWT,还有什么认证方案?

答案

方案优点缺点适用场景
JWT无状态、跨服务无法主动失效API 服务
Session可主动失效有状态、需存储传统 Web
API Key简单不够安全服务间调用
OAuth 2.0标准化、第三方登录复杂用户认证

相关链接