Rust JWT认证库alcoholic_jwt的使用:轻量级JSON Web Token解析与验证库

alcoholic_jwt

这是一个用于使用JWKS中的密钥验证RS256 JWT的库。仅此而已,不多不少。

RS256是JWT最常用的非对称签名机制,例如在Google或Aprila的API中会遇到。

这个库的名称源于尝试使用其他Rust库实现类似功能时可能产生的副作用。

使用概述

您正在从某些使用RS256签名并在JWKS格式中提供其公钥的身份验证提供程序检索JWT。

对于在token头中提供用于签名的密钥ID(kid声明)的token示例:

extern crate alcoholic_jwt;

use alcoholic_jwt::{JWKS, Validation, validate, token_kid};

// 这里隐含的函数通常会执行HTTP-GET
// 在身份验证提供程序的JWKS-URL上,并将结果反序列化到`alcoholic_jwt::JWKS`结构体中
let jwks: JWKS = jwks_fetching_function();

let token: String = some_token_fetching_function();

// 提供了几种内置验证类型:
let validations = vec![
  Validation::Issuer("auth.test.aprila.no".into()),
  Validation::SubjectPresent,
];

// 如果JWKS包含多个密钥,首先需要从token头中获取正确的KID
let kid = token_kid(&token)
    .expect("Failed to decode token headers")
    .expect("No 'kid' claim present in token");

let jwk = jwks.find(&kid).expect("Specified key not found in set");

validate(token, jwk, validations).expect("Token validation has failed!");

底层实现

该库旨在仅使用可信赖的现成组件来完成工作。加密操作由openssl crate提供,JSON序列化由serde_json提供。

贡献

该项目在TVL monorepo中开发。要处理它,您可以使用整个存储库的本地克隆或仅克隆alcoholic_jwt子树。

请遵循TVL贡献指南。

完整示例代码

use alcoholic_jwt::{JWKS, Validation, validate, token_kid};
use serde_json::{json, from_value};
use reqwest;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 1. 获取JWKS (JSON Web Key Set)
    let jwks_url = "https://your-auth-provider.com/.well-known/jwks.json";
    let jwks: JWKS = reqwest::get(jwks_url)
        .await?
        .json()
        .await?;

    // 2. 获取要验证的token (通常来自HTTP请求头)
    let token = "your.jwt.token.here".to_string();

    // 3. 定义验证规则
    let validations = vec![
        Validation::Issuer("your-issuer".into()),
        Validation::SubjectPresent,
        Validation::NotExpired,
    ];

    // 4. 从token中提取kid
    let kid = match token_kid(&token) {
        Ok(Some(k)) => k,
        Ok(None) => return Err("No 'kid' claim present in token".into()),
        Err(e) => return Err(format!("Failed to decode token headers: {}", e).into()),
    };

    // 5. 在JWKS中查找对应的密钥
    let jwk = jwks.find(&kid)
        .ok_or("Specified key not found in set")?;

    // 6. 验证token
    match validate(token, jwk, validations) {
        Ok(_) => println!("Token is valid!"),
        Err(e) => println!("Token validation failed: {}", e),
    }

    Ok(())
}

这个完整示例演示了如何:

  1. 从身份提供者获取JWKS
  2. 获取待验证的JWT token
  3. 设置验证规则(颁发者、主题存在性、未过期)
  4. 从token中提取kid
  5. 在JWKS中查找对应的公钥
  6. 执行验证

注意:实际使用时需要替换示例中的URL、token和验证参数为您的实际值。


1 回复

Rust JWT认证库alcoholic_jwt的使用:轻量级JSON Web Token解析与验证库

介绍

alcoholic_jwt是一个轻量级的Rust库,用于解析和验证JSON Web Tokens(JWT)。它提供了简单直观的API来处理JWT的验证过程,支持常见的加密算法如HS256、RS256等。

主要特点:

  • 支持常见的JWT算法(HS256, HS384, HS512, RS256, RS384, RS512)
  • 轻量级且易于使用
  • 可验证令牌过期时间(exp)、生效时间(nbf)等标准声明
  • 可自定义验证规则

完整示例代码

下面是一个完整的JWT验证示例,包含了令牌生成、验证和解码:

use alcoholic_jwt::{validate, token_decode, Validation, ValidJWT};
use serde::{Deserialize, Serialize};
use jsonwebtoken::{encode, EncodingKey, Header};
use std::time::{SystemTime, UNIX_EPOCH};

// 定义JWT声明结构体
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
    sub: String,
    company: String,
    exp: u64,
    role: String,
}

fn main() {
    // 1. 生成JWT令牌
    let token = generate_jwt_token();
    println!("Generated token: {}", token);
    
    // 2. 验证JWT令牌
    validate_jwt_token(&token);
    
    // 3. 解码令牌而不验证
    decode_jwt_token(&token);
}

fn generate_jwt_token() -> String {
    // 设置过期时间为1小时后
    let exp = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_secs() + 3600;
    
    // 创建声明
    let claims = Claims {
        sub: "1234567890".to_owned(),
        company: "ACME".to_owned(),
        exp,
        role: "admin".to_owned(),
    };
    
    // 使用HS256算法生成令牌
    encode(
        &Header::default(),
        &claims,
        &EncodingKey::from_secret("your-256-bit-secret".as_ref()),
    ).unwrap()
}

fn validate_jwt_token(token: &str) {
    // 验证配置
    let validations = vec![
        Validation::SubjectPresent,
        Validation::NotExpired,
        Validation::Custom(|claims| {
            if claims.get("role").and_then(|v| v.as_str()) == Some("admin") {
                Ok(())
            } else {
                Err("User is not an admin".into())
            }
        }),
    ];

    // 用于HMAC验证的密钥
    let secret = "your-256-bit-secret".as_bytes();
    
    // 验证令牌
    match validate(token, secret, validations) {
        Ok(token_claims) => {
            println!("Token is valid.");
            println!("Claims: {:?}", token_claims.claims);
        }
        Err(e) => {
            println!("Token validation failed: {:?}", e);
        }
    }
}

fn decode_jwt_token(token: &str) {
    // 解码令牌而不验证
    match token_decode::<serde_json::Value>(token) {
        Ok(decoded) => {
            println!("Decoded token header: {:?}", decoded.header);
            println!("Decoded token claims: {:?}", decoded.claims);
        }
        Err(e) => println!("Failed to decode token: {}", e),
    }
}

代码说明

  1. 令牌生成

    • 使用jsonwebtoken库的encode函数生成JWT令牌
    • 设置过期时间为当前时间+3600秒(1小时)
    • 使用HS256算法和密钥"your-256-bit-secret"进行签名
  2. 令牌验证

    • 使用alcoholic_jwtvalidate函数验证令牌
    • 检查主题是否存在、令牌是否过期
    • 自定义验证检查角色是否为"admin"
  3. 令牌解码

    • 使用token_decode函数解码令牌而不验证
    • 可以查看令牌的头信息和声明内容

注意事项

  1. 生产环境中应使用更强的密钥,不要使用示例中的简单密钥
  2. 对于RS256等非对称算法,需要配置公钥或JWKS
  3. 确保正确处理验证错误
  4. 定期检查库的更新以修复潜在的安全问题

这个完整示例展示了alcoholic_jwt库的主要功能,包括令牌验证、自定义验证和解码功能。

回到顶部