sa_token_core/token/
generator.rs1use 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 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 pub fn generate(config: &SaTokenConfig) -> TokenValue {
40 Self::generate_with_login_id(config, "")
41 }
42
43 pub fn generate_uuid() -> TokenValue {
45 TokenValue::new(Uuid::new_v4().to_string())
46 }
47
48 pub fn generate_simple_uuid() -> TokenValue {
50 TokenValue::new(Uuid::new_v4().simple().to_string())
51 }
52
53 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 pub fn generate_jwt(config: &SaTokenConfig, login_id: &str) -> TokenValue {
70 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 let secret = config.jwt_secret_key.as_ref()
79 .expect("JWT secret key is required when using JWT token style");
80
81 let algorithm = config.jwt_algorithm.as_ref()
83 .and_then(|alg| Self::parse_jwt_algorithm(alg))
84 .unwrap_or(JwtAlgorithm::HS256);
85
86 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 let mut claims = JwtClaims::new(effective_login_id);
99
100 if config.timeout > 0 {
102 claims.set_expiration(config.timeout);
103 }
104
105 match jwt_manager.generate(&claims) {
107 Ok(token) => TokenValue::new(token),
108 Err(e) => {
109 eprintln!("Failed to generate JWT token: {:?}", e);
110 Self::generate_uuid()
112 }
113 }
114 }
115
116 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 pub fn generate_hash(login_id: &str) -> TokenValue {
140 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 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 let mut hasher = Sha256::new();
175 hasher.update(uuid.as_bytes());
176 let result = hasher.finalize();
177 let suffix = hex::encode(&result[..8]); TokenValue::new(format!("{}_{}", timestamp, suffix))
180 }
181
182 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}