小工具
JWT使用
JWT简介
JWT 是 JSON Web Tokens 的缩写,一般被放置在 Http 请求的 Header 中, 如:
Authorization:Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsaXNpIiwiaWF0IjoxNzA1MjIyNDM2LCJleHAiOjE3MDUyMjMwMzZ9.Cb8Gp1ivVQKdNckzw70nD3ligabtwbAQzCl3fytjZCk
一个 JWT 包含 3 个部分:头部 Header,数据 Payload,签名 Signature,用点做间隔,如上面Bearer后面的token字符串的前两部分可解析为:
Header(eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9):
{"alg":"HS256","typ":"JWT"}
Payload(eyJzdWIiOiJsaXNpIiwiaWF0IjoxNzA1MjIyNDM2LCJleHAiOjE3MDUyMjMwMzZ9):
{"sub":"lisi","iat":1705222436,"exp":1705223036}
代码示例
Cargo.toml
[dependencies]
# jwt
jsonwebtoken = "9.2.0"
# 序列化反序列化
serde = {version = "1.0.194", features = ["derive"] }
# 时间格式化
chrono = { version = "0.4.31", features = [] }
结构体定义
use serde::{Deserialize, Serialize};
/// token payload中所包含的内容
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TokenClaims {
pub sub: String, // username或者user id
pub iat: usize, // token创建的时间
pub exp: usize, // token过期的时间
}
生成token
use jsonwebtoken::{encode, EncodingKey, Header};
/// 生成token
/// token_timeout:超时时间, 单位60s
/// secret: HMAC 密钥
pub fn gen_token(
username: String,
token_timeout: i64,
secret: String,
) -> Result<String, Box<dyn std::error::Error>> {
// 创建TokenClaims对象
let iat = chrono::Local::now();
let exp = iat + chrono::Duration::seconds(token_timeout); // 60分钟过期
let token_claims = TokenClaims {
sub: username,
iat: iat.timestamp() as usize,
exp: exp.timestamp() as usize,
};
// 对token进行编码
let token = encode(
&Header::default(),
&token_claims,
&EncodingKey::from_secret(secret.as_bytes()),
)?;
Ok(token)
}
解析token
use jsonwebtoken::{decode, DecodingKey, Validation};
/// 解析token
fn parse_token(secret: &str, token: &str) -> Result<TokenClaims, Box<dyn std::error::Error>> {
// 解析token
let token_claims = decode::<TokenClaims>(
&token,
&DecodingKey::from_secret(secret.as_bytes()),
// 默认的Validation配置确保加密算法为 HS256 并且令牌不会过期。
&Validation::default(),
)?
.claims;
Ok(token_claims)
}
使用示例
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 生成token
let username = "lisi";
let secret = "123456";
let timeout = 600; // 超时时间 600s
let token = gen_token(username.to_string(), timeout, secret.to_string())?;
println!("token:{}", token);
// 解析token
let token_claims = parse_token(secret, token.as_str())?;
println!(
"username:{:?}, iat:{:?}, exp:{:?}",
token_claims.sub, token_claims.iat, token_claims.exp
);
//
Ok(())
}
运行结果示例:
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
Running `target/debug/jwt`
token:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsaXNpIiwiaWF0IjoxNzA1MjIyNDM2LCJleHAiOjE3MDUyMjMwMzZ9.Cb8Gp1ivVQKdNckzw70nD3ligabtwbAQzCl3fytjZCk
username:"lisi", iat:1705222436, exp:1705223036