9个版本

0.5.1 2024年5月20日
0.5.0 2024年4月16日
0.4.0 2023年7月18日
0.3.0 2023年7月17日
0.1.0 2019年12月20日

#509Web编程

Download history 12/week @ 2024-04-19 139/week @ 2024-05-17 13/week @ 2024-05-24 25/week @ 2024-06-21 32/week @ 2024-06-28 56/week @ 2024-07-05 3/week @ 2024-07-12 138/week @ 2024-07-26 13/week @ 2024-08-02

每月155次下载

Apache-2.0

36KB
594

jwt-rust

jwts jwts jwts jwts

jwt

JSON Web令牌的Rust实现。

示例

编码

use jwts::{Claims, jws};
use jwts::jws::Header;
use jwts::jws::alg::HS256;

let claims = Claims {
    iss: Some("sea".to_owned()),
    ..Default::default()
};
jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();

解码

use jwts::{Claims, jws};
use jwts::jws::{Header, NoVerify, Token, VerifyWith};
use jwts::jws::alg::HS256;

let claims = Claims::default();
let token = jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();

let Token {..} = jws::decode::<Claims>(&token, NoVerify).unwrap(); // no verify
let Token {..} = jws::decode::<Claims>(&token, VerifyWith::<HS256>(b"secret")).unwrap(); // verify with algorithm and key

验证声明

use std::collections::HashMap;
use std::time::{Duration, SystemTime};
use jwts::Claims;
use jwts::validate::{ExpectAud, ExpectIss, ExpectJti, ExpectSub, ExpiredTime, IssuedAtTime, NotBeforeTime, Validate};

let claims = Claims {
    iss: Some("sea".to_owned()),
    sub: Some("subject".to_owned()),
    aud: Some("audience".to_owned()),
    jti: Some("id".to_owned()),
    ..Default::default()
};
let claims = claims
    .issued_now()
    .expired_in(Duration::from_secs(1))
    .not_before(SystemTime::now());

claims.validate(IssuedAtTime).unwrap();
claims.validate(NotBeforeTime).unwrap();
claims.validate(ExpiredTime).unwrap();
claims.validate(ExpectIss("sea")).unwrap();
claims.validate(ExpectSub("subject")).unwrap();
claims.validate(ExpectAud("audience")).unwrap();
claims.validate(ExpectJti("id")).unwrap();

// builtin validation works with any `Serialize` type:
let claims = HashMap::from([("iss", "sea")]);
claims.validate(ExpectIss("sea")).unwrap();

自定义声明类型

use std::collections::HashMap;
use serde_derive::{Deserialize, Serialize};
use jwts::jws;
use jwts::jws::{Header, Token, VerifyWith};
use jwts::jws::alg::HS256;

#[derive(Debug, Serialize, Deserialize)]
struct CustomClaims {
    iss: String,
}

let claims = CustomClaims {
    iss: "sea".to_owned(),
};
let token = jws::encode::<HS256>(Header::default(), &claims, b"secret").unwrap();
let Token {..} = jws::decode::<CustomClaims>(&token, VerifyWith::<HS256>(b"secret")).unwrap();

// Or use a map directly
let claims = HashMap::from([("iss", "sea")]);
let Token {..} = jws::decode::<HashMap<String, String>>(&token, VerifyWith::<HS256>(b"secret")).unwrap();

自定义算法

use jwts::{Claims, Error, jws};
use jwts::jws::{Algorithm, Header, Token, VerifyWith};

pub struct None;

impl Algorithm for None {
    type SignKey = ();
    type VerifyKey = ();

    fn name() -> &'static str {
        "None"
    }

    fn sign(data: impl AsRef<[u8]>, key: &Self::SignKey) -> Result<Vec<u8>, Error> {
        Ok([].into())
    }

    fn verify(data: impl AsRef<[u8]>, sig: impl AsRef<[u8]>, key: &Self::VerifyKey) -> Result<(), Error> {
        sig.as_ref().is_empty().then_some(()).ok_or(Error::InvalidSignature)
    }
}

let claims = Claims::default();
let token = jws::encode::<None>(Header::default(), &claims, &()).unwrap();
let Token {..} = jws::decode::<Claims>(&token, VerifyWith::<None>(&())).unwrap();

自定义验证

use jwts::{Claims, Error, jws};
use jwts::jws::{Algorithm, Header, Token, Verify};
use jwts::jws::alg::HS256;

pub struct CustomVerify;

impl Verify<Claims> for CustomVerify {
    fn verify(&self, f2s: &str, signature: &[u8], header: &Header, payload: &Claims) -> Result<(), Error> {
        HS256::verify(f2s, signature, b"secret")
    }
}

let token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzZWEifQ.L0DLtDjydcSK-c0gTyOYbmUQ_LUCZzqAGCINn2OLhFs";
let Token {..} = jws::decode::<Claims>(&token, CustomVerify).unwrap();

自定义声明验证

use jwts::Claims;
use jwts::validate::{Validate, Validation};

pub struct CustomValidation;

impl Validation<Claims> for CustomValidation {
    type Error = ();

    fn validate(&self, claims: &Claims) -> Result<(), Self::Error> {
        claims.aud.is_some().then_some(()).ok_or(())
    }
}

let claims = Claims {
    aud: Some("audience".to_owned()),
    ..Default::default()
};
claims.validate(CustomValidation).unwrap();

算法

使用crate aws-lc-rs 签名和验证。

  • HS256 - 使用SHA-256的HMAC
  • HS384 - 使用SHA-384的HMAC
  • HS512 - 使用SHA-512的HMAC
  • RS256 - 使用SHA-256的RSASSA-PKCS1-v1_5
  • RS384 - 使用SHA-384的RSASSA-PKCS1-v1_5
  • RS512 - 使用SHA-512的RSASSA-PKCS1-v1_5
  • ES256 - 使用P-256和SHA-256的ECDSA
  • ES384 - 使用P-384和SHA-384的ECDSA
  • ES512 - 使用P-521和SHA-512的ECDSA
  • PS256 - 使用SHA-256和MGF1与SHA-256的RSASSA-PSS
  • PS384 - 使用SHA-384和MGF1与SHA-384的RSASSA-PSS
  • PS512 - 使用SHA-512和MGF1与SHA-512的RSASSA-PSS

从0.2迁移

<= 0.2 >= 0.4
令牌::sign jws::encode
令牌::decode jws::decode with NoVerify
令牌::verify_with_key jws::decode with VerifyWith
令牌::verify_with_key_resolver jws::decode with custom verify
令牌::validate_claims 验证::validate

更多

RFC 7519 JSON Web Token (JWT)

RFC 7515 JSON Web Signature (JWS)

RFC 7518 JSON Web Algorithms (JWA)

许可证

Apache 2.0许可证

依赖项

~50MB
~1.5M SLoC