Rust JWT处理库jwt-compact的使用,提供轻量高效的JSON Web Token生成与验证功能
Rust JWT处理库jwt-compact的使用,提供轻量高效的JSON Web Token生成与验证功能
jwt-compact是一个专注于类型安全和安全加密原语的轻量级JSON Web Token(JWT)实现库。
基本用法
首先在Cargo.toml
中添加依赖:
[dependencies]
jwt-compact = "0.8.0"
基本令牌生命周期示例
以下是内容中提供的基本令牌生命周期示例:
use chrono::{Duration, Utc};
use jwt_compact::{prelude::*, alg::{Hs256, Hs256Key}};
use serde::{Serialize, Deserialize};
/// 自定义令牌中的声明
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct CustomClaims {
#[serde(rename = "sub")]
subject: String,
// 其他字段...
}
// 选择令牌创建/验证的时间相关选项
let time_options = TimeOptions::default();
// 创建一个对称HMAC密钥,将用于创建和验证令牌
let key = Hs256Key::new(b"super_secret_key_donut_steel");
// 创建一个令牌
let header = Header::empty().with_key_id("my-key");
let claims = Claims::new(CustomClaims { subject: "alice".to_owned() })
.set_duration_and_issuance(&time_options, Duration::hours(1))
.set_not_before(Utc::now());
let token_string = Hs256.token(&header, &claims, &key)?;
println!("token: {token_string}");
// 解析令牌
let token = UntrustedToken::new(&token_string)?;
// 在验证令牌之前,我们可以使用`Header.key_id`字段找到签署令牌的密钥
assert_eq!(token.header().key_id.as_deref(), Some("my-key");
// 验证令牌完整性
let token: Token<CustomClaims> = Hs256.validator(&key).validate(&token)?;
// 验证附加条件
token.claims()
.validate_expiration(&time_options)?
.validate_maturity(&time_options)?;
Ok::<_, anyhow::Error>(())
完整示例代码
下面是一个更完整的JWT生成与验证示例:
use chrono::{Duration, Utc};
use jwt_compact::{prelude::*, alg::{Hs256, Hs256Key}};
use serde::{Serialize, Deserialize};
use anyhow::Result;
#[derive(Debug, PartialEq, Serialize, Deserialize)]
struct CustomClaims {
#[serde(rename = "sub")]
subject: String,
#[serde(rename = "role")]
user_role: String,
#[serde(rename = "exp")]
expiration: Option<i64>,
}
fn main() -> Result<()> {
// 1. 创建令牌
let token = create_jwt_token()?;
println!("Generated token: {}", token);
// 2. 验证令牌
validate_jwt_token(&token)?;
println!("Token validated successfully!");
Ok(())
}
fn create_jwt_token() -> Result<String> {
// 时间选项
let time_options = TimeOptions::default();
// 创建HMAC密钥
let key = Hs256Key::new(b"super_secret_key_donut_steel");
// 创建令牌头
let header = Header::empty()
.with_key_id("user-auth-key")
.with_algorithm("HS256");
// 创建自定义声明
let custom_claims = CustomClaims {
subject: "user123".to_owned(),
user_role: "admin".to_owned(),
expiration: None, // 将由set_duration_and_issuance设置
};
// 创建并配置Claims
let claims = Claims::new(custom_claims)
.set_duration_and_issuance(&time_options, Duration::hours(1))
.set_not_before(Utc::now());
// 生成令牌字符串
Hs256.token(&header, &claims, &key).map_err(Into::into)
}
fn validate_jwt_token(token_str: &str) -> Result<()> {
// 时间选项
let time_options = TimeOptions::default();
// 使用相同的HMAC密钥
let key = Hs256Key::new(b"super_secret_key_donut_steel");
// 解析未经验证的令牌
let untrusted_token = UntrustedToken::new(token_str)?;
// 验证令牌签名
let token: Token<CustomClaims> = Hs256.validator(&key).validate(&untrusted_token)?;
// 验证时间相关声明
token.claims()
.validate_expiration(&time_options)?
.validate_maturity(&time_options)?;
// 验证自定义声明
let claims = token.claims();
println!("Subject: {}", claims.custom.subject);
println!("Role: {}", claims.custom.user_role);
Ok(())
}
特性
- 算法特定的签名和验证密钥(即类型安全)
- 来自RFC 7518的密钥强度要求通过包装类型表达
- 易于扩展以支持新的签名算法
- 支持更紧凑的CBOR编码声明
- 基本的JWK功能,用于从人类可读格式(JSON/YAML/TOML)转换密钥和计算密钥指纹
- 通过纯Rust
sha2
crate实现HS256
、HS384
和HS512
算法 - 支持Ed25519椭圆曲线的
EdDSA
算法和secp256k1椭圆曲线的ES256K
算法 - 通过纯Rust
p256
crate支持ES256
算法 - 通过纯Rust
rsa
crate支持RSA算法(RS*
和PS*
) - 支持
no_std
模式
替代方案
根据用例不同,jsonwebtoken
、frank_jwt
或biscuit
可能是可行的替代方案(例如它们似乎都没有实现EdDSA
或ES256K
算法)。
1 回复
Rust JWT处理库jwt-compact使用指南
jwt-compact
是一个轻量级、高效的Rust库,用于生成和验证JSON Web Tokens(JWT)。它专注于简单性和性能,同时提供必要的安全功能。
主要特性
- 轻量级实现,无多余依赖
- 支持HS256, HS384, HS512签名算法
- 支持ES256, ES384, ES512签名算法
- 支持RS256, RS384, RS512签名算法
- 支持自定义声明验证
- 时间验证(exp, nbf, iat)
- 无标准库支持(no_std)
安装
在Cargo.toml中添加依赖:
[dependencies]
jwt-compact = "0.5"
基本用法示例
生成Token示例
use jwt_compact::{alg::Hs256, AlgorithmExt, Claims, Header, TimeOptions, Token};
use serde::{Deserialize, Serialize};
// 自定义声明结构体
#[derive(Debug, Serialize, Deserialize)]
pub struct CustomClaims {
pub is_admin: bool,
pub user_id: String,
}
fn main() {
// 创建HS256算法的签名密钥
let key = Hs256.generate_key();
// 创建时间选项
let time_opts = TimeOptions::default();
// 创建自定义声明数据
let my_claims = CustomClaims {
is_admin: true,
user_id: "12345".to_owned(),
};
// 创建JWT声明,设置7天有效期
let claims = Claims::new(my_claims)
.set_duration_and_issuance(&time_opts, chrono::Duration::days(7));
// 生成token
let header = Header::empty().with_token_type("JWT");
let token = Hs256.token(header, &claims, &key).unwrap();
println!("生成的Token: {}", token);
}
验证Token示例
use jwt_compact::{alg::Hs256, AlgorithmExt, Validation, UntrustedToken};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct CustomClaims {
pub is_admin: bool,
pub user_id: String,
}
fn main() {
// 假设从客户端接收到的token字符串
let token_str = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...";
// 使用与生成时相同的密钥
let key = Hs256.generate_key();
// 解析未验证的token
let untrusted_token = UntrustedToken::new(&token_str).unwrap();
// 创建验证器
let validation = Validation::default();
// 验证token完整性
let token: Token<CustomClaims> = Hs256.validate_integrity(&untrusted_token, &key, &validation)
.unwrap();
// 获取并打印声明信息
let claims = token.claims();
println!("用户ID: {}", claims.custom.user_id);
println!("管理员权限: {}", claims.custom.is_admin);
println!("过期时间: {:?}", claims.expiration);
}
完整示例代码
以下是一个完整的JWT生成和验证流程示例:
use jwt_compact::{alg::Hs256, AlgorithmExt, Claims, Header, TimeOptions, Token, UntrustedToken, Validation};
use serde::{Deserialize, Serialize};
use chrono::{Duration, Utc};
// 自定义声明结构体
#[derive(Debug, Serialize, Deserialize)]
struct UserClaims {
user_id: u64,
username: String,
roles: Vec<String>,
}
fn main() {
// 1. 生成JWT Token
// 创建HS256密钥
let key = Hs256.generate_key();
// 创建时间选项
let time_opts = TimeOptions::new(Utc::now);
// 创建用户声明
let user_claims = UserClaims {
user_id: 42,
username: "john_doe".to_string(),
roles: vec!["admin".to_string(), "user".to_string()],
};
// 构建JWT声明,设置1小时有效期
let claims = Claims::new(user_claims)
.set_duration_and_issuance(&time_opts, Duration::hours(1));
// 生成Token
let header = Header::empty().with_token_type("JWT");
let token = Hs256.token(header, &claims, &key).unwrap();
println!("生成的JWT Token:\n{}\n", token);
// 2. 验证JWT Token
// 将Token转换为字符串形式(模拟传输)
let token_str = token.to_string();
// 解析未验证的Token
let untrusted_token = UntrustedToken::new(&token_str).unwrap();
// 创建自定义验证规则
let mut validation = Validation::default();
validation.required_claims.remove("exp"); // 可选:不强制要求过期时间
// 验证Token
let verified_token: Token<UserClaims> = Hs256
.validate_integrity(&untrusted_token, &key, &validation)
.unwrap();
// 获取验证后的声明
let verified_claims = verified_token.claims();
println!("验证后的用户声明:");
println!("用户ID: {}", verified_claims.custom.user_id);
println!("用户名: {}", verified_claims.custom.username);
println!("角色: {:?}", verified_claims.custom.roles);
println!("签发时间: {:?}", verified_claims.issued_at);
println!("过期时间: {:?}", verified_claims.expiration);
}
高级用法示例
自定义验证规则
use jwt_compact::{Validation, ValidationError};
// 创建自定义验证器
let mut validation = Validation::default();
validation.required_claims.remove("exp"); // 不要求过期时间
// 添加自定义验证逻辑
validation.invalidate_if = Some(Box::new(|claims: &UserClaims| {
// 检查用户是否有admin角色
if !claims.roles.contains(&"admin".to_string()) {
Err(ValidationError::new("需要管理员权限"))
} else {
Ok(())
}
}));
使用ES256算法示例
use jwt_compact::{alg::Es256, AlgorithmExt};
use p256::ecdsa::SigningKey;
use rand::thread_rng;
// 生成ES256密钥对
let signing_key = SigningKey::random(&mut thread_rng());
let verifying_key = signing_key.verifying_key();
// 创建用户声明
let claims = Claims::new(UserClaims {
user_id: 1,
username: "admin".to_string(),
roles: vec!["super_admin".to_string()],
});
// 使用ES256算法生成Token
let token = Es256.token(Header::default(), &claims, &signing_key).unwrap();
// 验证Token
let untrusted_token = UntrustedToken::new(&token).unwrap();
let _verified_token = Es256.validate_integrity(&untrusted_token, &verifying_key, &Validation::default())
.unwrap();
性能建议
- 对于对称加密(HS*),可以缓存密钥生成结果
- 对于非对称加密(RS*, ES*),可以缓存公钥验证对象
- 重用Validation对象而不是每次都创建新的
注意事项
- 确保妥善保管签名密钥
- 合理设置token过期时间
- 验证所有必要的声明
- 在生产环境中使用强加密算法(如RS256或ES256而非HS256)