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