sa_token_core/token/
generator.rs

1// Author: 金书记
2//
3//! Token Generator | Token 生成器
4//!
5//! Supports multiple token styles including UUID, Random, and JWT
6//! 支持多种 Token 风格,包括 UUID、随机字符串和 JWT
7
8use uuid::Uuid;
9use crate::config::{TokenStyle, SaTokenConfig};
10use crate::token::TokenValue;
11use crate::token::jwt::{JwtManager, JwtClaims, JwtAlgorithm};
12use chrono::Utc;
13use sha2::{Sha256, Digest};
14
15pub struct TokenGenerator;
16
17impl TokenGenerator {
18    /// Generate token based on configuration | 根据配置生成 token
19    ///
20    /// # Arguments | 参数
21    ///
22    /// * `config` - Sa-token configuration | Sa-token 配置
23    /// * `login_id` - User login ID (required for JWT) | 用户登录ID(JWT 必需)
24    pub fn generate_with_login_id(config: &SaTokenConfig, login_id: &str) -> TokenValue {
25        match config.token_style {
26            TokenStyle::Uuid => Self::generate_uuid(),
27            TokenStyle::SimpleUuid => Self::generate_simple_uuid(),
28            TokenStyle::Random32 => Self::generate_random(32),
29            TokenStyle::Random64 => Self::generate_random(64),
30            TokenStyle::Random128 => Self::generate_random(128),
31            TokenStyle::Jwt => Self::generate_jwt(config, login_id),
32            TokenStyle::Hash => Self::generate_hash(login_id),
33            TokenStyle::Timestamp => Self::generate_timestamp(),
34            TokenStyle::Tik => Self::generate_tik(),
35        }
36    }
37    
38    /// Generate token (backward compatible) | 根据配置生成 token(向后兼容)
39    pub fn generate(config: &SaTokenConfig) -> TokenValue {
40        Self::generate_with_login_id(config, "")
41    }
42    
43    /// 生成 UUID 风格的 token
44    pub fn generate_uuid() -> TokenValue {
45        TokenValue::new(Uuid::new_v4().to_string())
46    }
47    
48    /// 生成简化的 UUID(去掉横杠)
49    pub fn generate_simple_uuid() -> TokenValue {
50        TokenValue::new(Uuid::new_v4().simple().to_string())
51    }
52    
53    /// 生成随机字符串
54    pub fn generate_random(length: usize) -> TokenValue {
55        use sha2::{Sha256, Digest};
56        let uuid = Uuid::new_v4();
57        let random_bytes = uuid.as_bytes();
58        let hash = Sha256::digest(random_bytes);
59        let hex_string = hex::encode(hash);
60        TokenValue::new(hex_string[..length.min(hex_string.len())].to_string())
61    }
62    
63    /// Generate JWT token | 生成 JWT token
64    ///
65    /// # Arguments | 参数
66    ///
67    /// * `config` - Sa-token configuration | Sa-token 配置
68    /// * `login_id` - User login ID | 用户登录ID
69    pub fn generate_jwt(config: &SaTokenConfig, login_id: &str) -> TokenValue {
70        // 如果 login_id 为空,则使用时间戳作为 login_id
71        let effective_login_id = if login_id.is_empty() {
72            Utc::now().timestamp_millis().to_string()
73        } else {
74            login_id.to_string()
75        };
76        
77        // Get JWT secret key | 获取 JWT 密钥
78        let secret = config.jwt_secret_key.as_ref()
79            .expect("JWT secret key is required when using JWT token style");
80        
81        // Parse algorithm | 解析算法
82        let algorithm = config.jwt_algorithm.as_ref()
83            .and_then(|alg| Self::parse_jwt_algorithm(alg))
84            .unwrap_or(JwtAlgorithm::HS256);
85        
86        // Create JWT manager | 创建 JWT 管理器
87        let mut jwt_manager = JwtManager::with_algorithm(secret, algorithm);
88        
89        if let Some(ref issuer) = config.jwt_issuer {
90            jwt_manager = jwt_manager.set_issuer(issuer);
91        }
92        
93        if let Some(ref audience) = config.jwt_audience {
94            jwt_manager = jwt_manager.set_audience(audience);
95        }
96        
97        // Create claims | 创建声明
98        let mut claims = JwtClaims::new(effective_login_id);
99        
100        // Set expiration | 设置过期时间
101        if config.timeout > 0 {
102            claims.set_expiration(config.timeout);
103        }
104        
105        // Generate JWT token | 生成 JWT token
106        match jwt_manager.generate(&claims) {
107            Ok(token) => TokenValue::new(token),
108            Err(e) => {
109                eprintln!("Failed to generate JWT token: {:?}", e);
110                // Fallback to UUID | 回退到 UUID
111                Self::generate_uuid()
112            }
113        }
114    }
115    
116    /// Parse JWT algorithm from string | 从字符串解析 JWT 算法
117    fn parse_jwt_algorithm(alg: &str) -> Option<JwtAlgorithm> {
118        match alg.to_uppercase().as_str() {
119            "HS256" => Some(JwtAlgorithm::HS256),
120            "HS384" => Some(JwtAlgorithm::HS384),
121            "HS512" => Some(JwtAlgorithm::HS512),
122            "RS256" => Some(JwtAlgorithm::RS256),
123            "RS384" => Some(JwtAlgorithm::RS384),
124            "RS512" => Some(JwtAlgorithm::RS512),
125            "ES256" => Some(JwtAlgorithm::ES256),
126            "ES384" => Some(JwtAlgorithm::ES384),
127            _ => None,
128        }
129    }
130    
131    /// Generate Hash style token | 生成 Hash 风格 token
132    ///
133    /// Uses SHA256 hash of login_id + timestamp + random UUID
134    /// 使用 SHA256 哈希:login_id + 时间戳 + 随机 UUID
135    ///
136    /// # Arguments | 参数
137    ///
138    /// * `login_id` - User login ID | 用户登录ID
139    pub fn generate_hash(login_id: &str) -> TokenValue {
140        // 如果 login_id 为空,使用时间戳代替
141        let login_id_value = if login_id.is_empty() {
142            Utc::now().timestamp_millis().to_string()
143        } else {
144            login_id.to_string()
145        };
146        
147        let timestamp = Utc::now().timestamp_millis();
148        let uuid = Uuid::new_v4();
149        let data = format!("{}{}{}", login_id_value, timestamp, uuid);
150        
151        let mut hasher = Sha256::new();
152        hasher.update(data.as_bytes());
153        let result = hasher.finalize();
154        let hash = hex::encode(result);
155        
156        TokenValue::new(hash)
157    }
158    
159    /// Generate Timestamp style token | 生成时间戳风格 token
160    ///
161    /// Format: timestamp_milliseconds + 16-char random suffix
162    /// 格式:毫秒级时间戳 + 16位随机后缀
163    ///
164    /// Example: 1760403556789_a3b2c1d4e5f6g7h8
165    /// 示例:1760403556789_a3b2c1d4e5f6g7h8
166    pub fn generate_timestamp() -> TokenValue {
167        use chrono::Utc;
168        use sha2::{Sha256, Digest};
169        
170        let timestamp = Utc::now().timestamp_millis();
171        let uuid = Uuid::new_v4();
172        
173        // Generate random suffix | 生成随机后缀
174        let mut hasher = Sha256::new();
175        hasher.update(uuid.as_bytes());
176        let result = hasher.finalize();
177        let suffix = hex::encode(&result[..8]); // 16 characters
178        
179        TokenValue::new(format!("{}_{}", timestamp, suffix))
180    }
181    
182    /// Generate Tik style token | 生成 Tik 风格 token
183    ///
184    /// Short 8-character alphanumeric token (URL-safe)
185    /// 短小精悍的8位字母数字 token(URL安全)
186    ///
187    /// Character set: A-Z, a-z, 0-9 (62 characters)
188    /// 字符集:A-Z, a-z, 0-9(62个字符)
189    ///
190    /// Example: aB3dE9fG
191    /// 示例:aB3dE9fG
192    pub fn generate_tik() -> TokenValue {
193        use sha2::{Sha256, Digest};
194        
195        const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
196        const TOKEN_LENGTH: usize = 8;
197        
198        let uuid = Uuid::new_v4();
199        let mut hasher = Sha256::new();
200        hasher.update(uuid.as_bytes());
201        let hash = hasher.finalize();
202        
203        let mut token = String::with_capacity(TOKEN_LENGTH);
204        for i in 0..TOKEN_LENGTH {
205            let idx = (hash[i] as usize) % CHARSET.len();
206            token.push(CHARSET[idx] as char);
207        }
208        
209        TokenValue::new(token)
210    }
211}