Skip to main content

server_common/
jwt.rs

1use chrono::{Duration, Utc};
2use jsonwebtoken::{Algorithm, DecodingKey, EncodingKey, Header, Validation, decode, encode};
3use serde::{Deserialize, Serialize};
4use server_config::{jwt::JwtConfig, uri::IgnoreUri};
5
6use crate::error::auth::AuthError;
7
8// 定义 JWT Claims
9#[derive(Debug, Serialize, Deserialize, Clone)]
10pub struct Claims {
11    pub sub: String, // 用户ID
12    pub exp: i64,    // 过期时间
13    pub iat: i64,    // 签发时间
14    pub data: Option<String>,
15}
16
17// Token 生成和验证
18pub struct JwtService {
19    config: JwtConfig,
20}
21
22impl JwtService {
23    pub fn new(mut config: JwtConfig) -> Self {
24        if let Some(data) = &mut config.ignore_uris {
25            JwtService::methods_to_uppercase(data);
26        }
27        Self { config }
28    }
29
30    // 生成 Token
31    pub fn generate_token(
32        &self,
33        user_info: &str,
34        data: Option<String>,
35    ) -> Result<String, jsonwebtoken::errors::Error> {
36        let now = Utc::now();
37        let exp = now + Duration::hours(self.config.expiration_hours);
38
39        let claims = Claims {
40            sub: user_info.to_string(),
41            exp: exp.timestamp(),
42            iat: now.timestamp(),
43            data,
44        };
45
46        encode(
47            &Header::default(),
48            &claims,
49            &EncodingKey::from_secret(self.config.secret.as_ref()),
50        )
51    }
52
53    // 验证 Token
54    pub fn verify_token(&self, token: &str) -> Result<Claims, AuthError> {
55        let token_data = decode::<Claims>(
56            token,
57            &DecodingKey::from_secret(self.config.secret.as_ref()),
58            &Validation::new(Algorithm::HS256),
59        )
60        .map_err(|_| AuthError::InvalidToken)?;
61
62        // 检查是否过期
63        let now = Utc::now().timestamp();
64        if token_data.claims.exp < now {
65            return Err(AuthError::ExpiredToken);
66        }
67
68        Ok(token_data.claims)
69    }
70
71    // 获取加密钥匙
72    pub fn get_secret(&self) -> String {
73        self.config.secret.clone()
74    }
75
76    // 获取过期时间戳
77    pub fn get_expiration(&self) -> i64 {
78        self.config.expiration_hours
79    }
80
81    // 获取忽略uri信息
82    pub fn is_ignore_uri(&self, uri: &str, method: &str) -> bool {
83        if let Some(data) = &self.config.ignore_uris {
84            for item in data.iter() {
85                // 判断是否在跳过验证路径中
86                if uri.starts_with(&item.path) && item.method.contains(&method.to_uppercase()) {
87                    return true;
88                }
89            }
90            false
91        } else {
92            false
93        }
94    }
95
96    // 将请求方法转大写
97    pub fn methods_to_uppercase(data: &mut [IgnoreUri]) {
98        for item in data.iter_mut() {
99            for method in item.method.iter_mut() {
100                *method = method.to_uppercase();
101            }
102        }
103    }
104}