1个版本 (0个不稳定版本)
8.3.0-surreal.1 | 2023年8月29日 |
---|
#539 在 编码 中排名
14,008 每月下载次数
在 57 个crate(6 个直接) 中使用
105KB
2K SLoC
jsonwebtoken
有关JSON Web Tokens的更多信息,请参阅 JSON Web Tokens。
安装
将以下内容添加到Cargo.toml
jsonwebtoken = "8"
# If you do not need pem decoding, you can disable the default feature `use_pem` that way:
# jsonwebtoken = {version = "8", default-features = false }
serde = {version = "1.0", features = ["derive"] }
最低要求的Rust版本是1.56。
算法
该库目前支持以下算法
- HS256
- HS384
- HS512
- RS256
- RS384
- RS512
- PS256
- PS384
- PS512
- ES256
- ES384
- EdDSA
使用方法
完整的示例可在examples目录中找到:一个基本的和一个带有自定义头部的示例。
关于导入和结构体
use serde::{Serialize, Deserialize};
use jsonwebtoken::{encode, decode, Header, Algorithm, Validation, EncodingKey, DecodingKey};
/// Our claims struct, it needs to derive `Serialize` and/or `Deserialize`
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
sub: String,
company: String,
exp: usize,
}
声明
可验证的声明字段。(见 验证)
#[derive(Debug, Serialize, Deserialize)]
struct Claims {
aud: String, // Optional. Audience
exp: usize, // Required (validate_exp defaults to true in validation). Expiration time (as UTC timestamp)
iat: usize, // Optional. Issued at (as UTC timestamp)
iss: String, // Optional. Issuer
nbf: usize, // Optional. Not Before (as UTC timestamp)
sub: String, // Optional. Subject (whom token refers to)
}
头部
默认算法是HS256,它使用共享密钥。
let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
自定义头部和更改算法
支持RFC中所有的参数,但默认头部只设置了typ
和alg
。如果您想设置kid
参数或更改算法等
let mut header = Header::new(Algorithm::HS512);
header.kid = Some("blabla".to_owned());
let token = encode(&header, &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
请查看examples/custom_header.rs
以获取完整的示例。
编码
// HS256
let token = encode(&Header::default(), &my_claims, &EncodingKey::from_secret("secret".as_ref()))?;
// RSA
let token = encode(&Header::new(Algorithm::RS256), &my_claims, &EncodingKey::from_rsa_pem(include_bytes!("privkey.pem"))?)?;
编码JWT需要3个参数
- 一个头部:
Header
结构体 - 一些声明:您的自定义结构体
- 一个密钥/密钥
当使用HS256、HS384或HS512时,密钥始终是类似于上面的共享密钥。当使用RSA/EC时,密钥应该是PEM或DER格式的私钥内容。
如果您的密钥是PEM格式,从性能的角度来看,最好在lazy_static
或类似的地方生成一次EncodingKey
并重用它。
解码
// `token` is a struct with 2 fields: `header` and `claims` where `claims` is your own struct.
let token = decode::<Claims>(&token, &DecodingKey::from_secret("secret".as_ref()), &Validation::default())?;
decode
可能因为各种原因出错
- 令牌或其签名无效
- 令牌有无效的base64
- 至少一个保留声明的验证失败
与编码一样,当使用HS256、HS2384或HS512时,密钥始终如示例中所示,是一个共享的秘密。当使用RSA/EC时,密钥应该是PEM(或在此情况下证书)或DER格式的公钥内容。
在某些情况下,例如不知道使用的算法或需要获取kid
时,可以选择仅解码头信息。
let header = decode_header(&token)?;
这不会执行任何签名验证或验证令牌声明。
您还可以使用RSA密钥的公钥组件以base64格式解码令牌。主要用例是JWK,其中您的公钥以如下JSON格式存在:
{
"kty":"RSA",
"e":"AQAB",
"kid":"6a7a119f-0876-4f7e-8d0f-bf3ea1391dd8",
"n":"yRE6rHuNR0QbHO3H3Kt2pOKGVhQqGZXInOduQNxXzuKlvQTLUTv4l4sggh5_CYYi_cvI-SXVT9kPWSKXxJXBXd_4LkvcPuUakBoAkfh-eiFVMh2VrUyWyj3MFl0HTVF9KwRXLAcwkREiS3npThHRyIxuy0ZMeZfxVL5arMhw1SRELB8HoGfG_AtH89BIE9jDBHZ9dLelK9a184zAf8LwoPLxvJb3Il5nncqPcSfKDDodMFBIMc4lQzDKL5gvmiXLXB1AGLm8KBjfE8s3L5xqi-yUod-j8MtvIj812dkS4QMiRVN_by2h3ZY8LYVGrqZXZTcgn2ujn8uKjXLZVD5TdQ"
}
// `token` is a struct with 2 fields: `header` and `claims` where `claims` is your own struct.
let token = decode::<Claims>(&token, &DecodingKey::from_rsa_components(jwk["n"], jwk["e"]), &Validation::new(Algorithm::RS256))?;
如果您的密钥是PEM格式,从性能角度考虑,最好在lazy_static
或类似的结构中一次性生成DecodingKey
并重用它。
将SEC1私钥转换为PKCS8
jsonwebtoken
目前只支持PKCS8格式的私EC密钥。如果您的密钥顶部有BEGIN EC PRIVATE KEY
,则这是一个SEC1类型,可以转换为PKCS8,如下所示:
openssl pkcs8 -topk8 -nocrypt -in sec1.pem -out pkcs8.pem
验证
此库会自动验证exp
声明,如果存在,则会验证nbf
。您还可以验证sub
、iss
和aud
,但这些需要在Validation
结构中设置预期值。
由于验证时间字段总是有点棘手,因为存在时钟偏差,您可以通过设置leeway
字段,为iat
、exp
和nbf
验证添加一些容差。
最后但同样重要的是,如果您不使用HS256
,则需要设置此令牌允许的算法。
查看examples/validation.rs
以获取完整的工作示例。
依赖项
~1–5.5MB
~130K SLoC