JSON Web Token Claims Expiry Validation
Sign and verify tokens with jsonwebtoken in Rust, validating registered claims, required fields, and clock tolerance windows.
Code
use jsonwebtoken::{decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation};
use serde::{Deserialize, Serialize};
use std::time::{SystemTime, UNIX_EPOCH};
#[derive(Debug, Serialize, Deserialize)]
struct SessionClaims {
sub: String,
role: String,
tenant: String,
exp: u64,
iat: u64,
}
fn now() -> u64 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs()
}
fn issue(key: &EncodingKey, subject: &str, role: &str, tenant: &str) -> String {
let claims = SessionClaims {
sub: subject.into(),
role: role.into(),
tenant: tenant.into(),
iat: now(),
exp: now() + 900, // 15 分钟访问令牌
};
encode(&Header::new(Algorithm::ES256), &claims, key).unwrap()
}
fn verify(
key: &DecodingKey,
token: &str,
required_tenant: &str,
) -> Result<SessionClaims, String> {
let mut validation = Validation::new(Algorithm::ES256);
validation.required_spec_claims.insert("exp".into());
validation.required_spec_claims.insert("sub".into());
validation.leeway = 5; // 时钟偏差容忍 5 秒
validation.validate_exp = true;
let data = decode::<SessionClaims>(token, key, &validation)
.map_err(|err| format!("token rejected: {err:?}"))?;
if data.claims.tenant != required_tenant {
return Err("tenant mismatch".into());
}
Ok(data.claims)
}
fn main() {
let encoding = EncodingKey::from_ec_pem(include_bytes!("../keys/private.pem")).unwrap();
let decoding = DecodingKey::from_ec_pem(include_bytes!("../keys/public.pem")).unwrap();
let token = issue(&encoding, "user-42", "editor", "acme");
match verify(&decoding, &token, "acme") {
Ok(claims) => println!("accepted: {} as {}", claims.sub, claims.role),
Err(err) => println!("rejected: {err}"),
}
match verify(&decoding, &token, "other-tenant") {
Ok(_) => unreachable!(),
Err(err) => println!("cross-tenant blocked: {err}"),
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.