如何在Rust中使用公钥证书验证JWT?
解决方案:用JWT crate结合X509证书验证RSA签名的JWT
1. 依赖配置
首先确保你的Cargo.toml包含正确的依赖,开启JWT crate的openssl和serde特性(用于解析声明):
[dependencies] jwt = { version = "0.16", features = ["openssl", "serde"] } x509-certificate = "0.10" openssl = "0.10" serde = { version = "1.0", features = ["derive"] }
2. 完整验证代码
你需要将X509证书中的公钥转换成OpenSSL的PKey类型,再结合JWT签名算法对应的摘要算法创建验证器,最后完成签名验证和声明解析:
use x509_certificate::certificate::X509Certificate; use jwt::{Token, VerifyWithKey}; use openssl::{pkey::PKey, hash::MessageDigest, sign::RsaWithDigest}; use serde::Deserialize; // 定义与JWT声明对应的结构体,根据你的实际声明字段调整 #[derive(Debug, Deserialize)] struct Claims { sub: String, exp: usize, // 其他需要的声明字段 } fn main() { let certificate: String = "-----BEGIN CERTIFICATE----- MII.......... -----END CERTIFICATE-----".to_owned(); let x509cert = X509Certificate::from_pem(certificate.as_bytes()).unwrap(); // 从证书中提取公钥的DER格式数据 let pub_key_der = x509cert.public_key_data(); // 解析DER格式公钥为OpenSSL PKey let pkey = PKey::public_key_from_der(pub_key_der).unwrap(); let token_str = "eyJhbGc.............."; // 根据JWT使用的算法创建验证器(示例为RS256,对应SHA256摘要) let verifying_alg = RsaWithDigest::new(MessageDigest::sha256()) .unwrap() .with_public_key(pkey) .unwrap(); // 验证签名并解析声明 let claims: Claims = Token::verify_with_key(token_str, &verifying_alg).unwrap(); println!("解析得到的声明: {:?}", claims); }
关键步骤说明
- 公钥转换:
X509Certificate::public_key_data()返回的是DER格式的公钥数据,需要用OpenSSL的PKey::public_key_from_der()转换成可用的公钥对象。 - 验证算法选择:要匹配JWT头部指定的算法(比如RS256对应
MessageDigest::sha256(),RS384对应sha384(),RS512对应sha512())。 - 声明解析:通过
serde派生Deserializetrait的结构体,可以自动将JWT负载映射到Rust结构体中。
关于选型:JWT crate vs 直接用OpenSSL
如果你只需要验证JWT签名+读取声明,JWT crate是更合适的选择:
- 它封装了JWT的所有核心逻辑:自动拆分令牌的Header/Payload/Signature部分,处理签名验证的细节,无需你手动处理字节编码、签名计算等底层操作。
- 直接使用OpenSSL的话,你需要自己实现JWT的解析(拆分三段Base64编码内容)、解码Header和Payload、手动执行签名验证逻辑,会增加很多不必要的代码复杂度,出错概率更高。
只有当你需要对JWT的验证流程做高度定制化的底层操作时,才考虑直接使用OpenSSL。
内容的提问来源于stack exchange,提问作者newbie
相关产品推荐
相关产品推荐

