Rust中的JWT令牌:库与身份验证实现

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust中的JWT令牌:库与身份验证实现

JSON Web Token (JWT) 是一种基于JSON格式的开放标准,用于创建访问令牌。在Rust生态系统中,通过多个高质量的库实现了JWT功能,其中领先的是jsonwebtoken。该工具提供了令牌的完整生命周期管理:创建、签名、验证和解码。



Rust中JWT的主要库

目前最流行的JWT crate包括:

  • jsonwebtoken — 支持HS256、RS256、EdDSA算法的主要库
  • jwt — 功能较基础的轻量级替代方案
  • biscuit — 支持复杂场景的高级库

本文将重点介绍jsonwebtoken,因为它是最成熟且文档最完善的解决方案。



安装与配置

在Cargo.toml中添加依赖:

[dependencies]jsonwebtoken = "9.3"serde = { version = "1.0", features = ["derive"] }chrono = "0.4"


创建与验证JWT令牌

以下是使用JWT实现身份验证的完整示例:



use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey};use serde::{Serialize, Deserialize};use chrono::{Utc, Duration};

#[derive(Debug, Serialize, Deserialize)]struct Claims { sub: String, // 用户标识符 exp: usize, // 令牌过期时间 iat: usize, // 令牌创建时间 role: String, // 用户角色}

fn create_token(user_id: &str, role: &str, secret: &str) -> Result { let now = Utc::now(); let claims = Claims { sub: user_id.to_string(), exp: (now + Duration::hours(24)).timestamp() as usize, iat: now.timestamp() as usize, role: role.to_string(), }; encode( &Header::default(), &claims, &EncodingKey::from_secret(secret.as_bytes()) )}

fn verify_token(token: &str, secret: &str) -> Result { let token_data = decode::( token, &DecodingKey::from_secret(secret.as_bytes()), &Validation::default() )?; Ok(token_data.claims)}


在Web应用程序中的实际使用

将JWT与Web框架(例如Actix-web或Axum)集成需要创建用于验证令牌的中间件:



use actix_web::{HttpRequest, HttpResponse, web, App, HttpServer, middleware::from_fn};use std::sync::Arc;

// 用于验证JWT的中间件async fn auth_middleware( req: HttpRequest,) -> Result { let auth_header = req.headers() .get("Authorization") .and_then(|v| v.to_str().ok()) .ok_or(HttpResponse::Unauthorized().json("缺少令牌"))?; let token = auth_header .strip_prefix("Bearer ") .ok_or(HttpResponse::Unauthorized().json("令牌格式无效"))?; verify_token(token, SECRET) .map_err(|_| HttpResponse::Unauthorized().json("令牌无效"))}

// 受保护端点async fn protected_endpoint(claims: Claims) -> HttpResponse { HttpResponse::Ok().json(claims)}


高级功能与最佳实践

  • 刷新令牌 — 使用短生命周期的访问令牌(15-30分钟)和长生命周期的刷新令牌(7-30天)
  • 密钥存储 — 切勿将密钥存储在代码中,应使用环境变量或安全存储
  • 签名算法 — 生产环境中建议使用RS256(非对称加密)而非HS256
  • 验证 — 始终验证令牌的过期时间、签发者和受众声明

推荐