1 个不稳定版本
0.17.0 | 2024年1月16日 |
---|
#1244 in 加密学
每月 下载 39 次
70KB
1.5K SLoC
JWT

一个 JSON Web 令牌库。
仅声明
如果您不关心该头部,只要头部被验证,就可以使用几个特质来完成签名和验证。
签名
声明可以是任何 serde::Serialize
类型,通常通过 serde_derive
派生。
use hmac::{Hmac, Mac};
use jwt::SignWithKey;
use sha2::Sha256;
use std::collections::BTreeMap;
let key: Hmac<Sha256> = Hmac::new_from_slice(b"some-secret").unwrap();
let mut claims = BTreeMap::new();
claims.insert("sub", "someone");
let token_str = claims.sign_with_key(&key).unwrap();
assert_eq!(token_str, "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzb21lb25lIn0.5wwE1sBrs-vftww_BGIuTVDeHtc1Jsjo-fiHhDwR8m0");
验证
声明可以是任何 serde::Deserialize
类型,通常通过 serde_derive
派生。
use hmac::{Hmac, Mac};
use jwt::VerifyWithKey;
use sha2::Sha256;
use std::collections::BTreeMap;
let key: Hmac<Sha256> = Hmac::new_from_slice(b"some-secret").unwrap();
let token_str = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzb21lb25lIn0.5wwE1sBrs-vftww_BGIuTVDeHtc1Jsjo-fiHhDwR8m0";
let claims: BTreeMap<String, String> = token_str.verify_with_key(&key).unwrap();
assert_eq!(claims["sub"], "someone");
头部和声明
如果您需要自定义头部,可以使用 Token
结构。为了方便,提供了一个 Header
结构,用于所有常用字段,但任何实现了 JoseHeader
的类型都可以使用。
签名
头部和声明都必须实现 serde::Serialize
。
use hmac::{Hmac, Mac};
use jwt::{AlgorithmType, Header, SignWithKey, Token};
use sha2::Sha384;
use std::collections::BTreeMap;
let key: Hmac<Sha384> = Hmac::new_from_slice(b"some-secret").unwrap();
let header = Header {
algorithm: AlgorithmType::Hs384,
..Default::default()
};
let mut claims = BTreeMap::new();
claims.insert("sub", "someone");
let token = Token::new(header, claims).sign_with_key(&key).unwrap();
assert_eq!(token.as_str(), "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJzb21lb25lIn0.WM_WnPUkHK6zm6Wz7zk1kmIxz990Te7nlDjQ3vzcye29szZ-Sj47rLNSTJNzpQd_");
验证
头部和声明都必须实现 serde::Deserialize
。
use hmac::{Hmac, Mac};
use jwt::{AlgorithmType, Header, Token, VerifyWithKey};
use sha2::Sha384;
use std::collections::BTreeMap;
let key: Hmac<Sha384> = Hmac::new_from_slice(b"some-secret").unwrap();
let token_str = "eyJhbGciOiJIUzM4NCJ9.eyJzdWIiOiJzb21lb25lIn0.WM_WnPUkHK6zm6Wz7zk1kmIxz990Te7nlDjQ3vzcye29szZ-Sj47rLNSTJNzpQd_";
let token: Token<Header, BTreeMap<String, String>, _> = VerifyWithKey::verify_with_key(token_str, &key).unwrap();
let header = token.header();
let claims = token.claims();
assert_eq!(header.algorithm, AlgorithmType::Hs384);
assert_eq!(claims["sub"], "someone");
存储
可以使用 Store
来表示按键 ID 索引的一组键。目前,这仅自动实现为具有 Borrow<str>
键的 BTreeMap
和 HashMap
。如果实现了特殊化,则将实现为所有具有 Index<&str>
特性的类型,就像之前一样。
对于特性和 SignWithStore
,关键ID将自动添加到裸声明的头中。因为声明没有指定关键ID的方式,所以需要一个关键ID和声明的元组。对于令牌,使用头部的关键ID来获取密钥。
对于特性和 VerifyWithStore
,将使用反序列化头部的关键ID来选择要使用的密钥。
use hmac::{Hmac, Mac};
use jwt::{Header, SignWithStore, Token, VerifyWithStore};
use sha2::Sha512;
use std::collections::BTreeMap;
let mut store: BTreeMap<_, Hmac<Sha512>> = BTreeMap::new();
store.insert("first_key", Hmac::new_from_slice(b"first").unwrap());
store.insert("second_key", Hmac::new_from_slice(b"second").unwrap());
let mut claims = BTreeMap::new();
claims.insert("sub", "someone");
let token_str = ("second_key", claims).sign_with_store(&store).unwrap();
assert_eq!(token_str, "eyJhbGciOiJIUzUxMiIsImtpZCI6InNlY29uZF9rZXkifQ.eyJzdWIiOiJzb21lb25lIn0.9gALQon5Mk8r4BjOZ2SJQlauGmT4WUhpN152x9dfKvkPON1VwEN09Id8vjQ0ABlfLJUTVNP36dsdrpYEZDLUcw");
let verified_token: Token<Header, BTreeMap<String, String>, _> = token_str.verify_with_store(&store).unwrap();
assert_eq!(verified_token.claims()["sub"], "someone");
assert_eq!(verified_token.header().key_id.as_ref().unwrap(), "second_key");
支持的算法
通过 RustCrypto 支持纯Rust HMAC。RSA和ECDSA签名的实现通过OpenSSL支持,默认情况下未启用。必须将OpenSSL类型包裹在 PKeyWithDigest
结构中。
- HS256
- HS384
- HS512
- RS256
- RS384
- RS512
- ES256
- ES384
- ES512
依赖项
~8.5MB
~183K SLoC