认证与授权
问题
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 | 标准化、第三方登录 | 复杂 | 用户认证 |