Skip to main content

sa_token_core/
config.rs

1// Author: 金书记
2//
3//! 配置模块
4
5use std::time::Duration;
6use std::sync::Arc;
7use serde::{Deserialize, Serialize};
8use sa_token_adapter::storage::SaStorage;
9use crate::event::SaTokenListener;
10
11/// sa-token 配置
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct SaTokenConfig {
14    /// Token 名称(例如在 header 或 cookie 中的键名)
15    pub token_name: String,
16    
17    /// Token 有效期(秒),-1 表示永久有效
18    pub timeout: i64,
19    
20    /// Token 最低活跃频率(秒),-1 表示不限制
21    /// 
22    /// 配合 auto_renew 使用时,表示自动续签的时长
23    pub active_timeout: i64,
24    
25    /// 是否开启自动续签(默认 false)
26    /// 
27    /// 如果设置为 true,在以下场景会自动续签 token:
28    /// - 调用 get_token_info() 时
29    /// - 中间件验证 token 时
30    /// - 调用无参数的 StpUtil 方法时
31    /// 
32    /// 续签时长由 active_timeout 决定:
33    /// - 如果 active_timeout > 0,则续签 active_timeout 秒
34    /// - 如果 active_timeout <= 0,则续签 timeout 秒
35    pub auto_renew: bool,
36    
37    /// 是否允许同一账号并发登录
38    pub is_concurrent: bool,
39    
40    /// 在多人登录同一账号时,是否共享一个 token
41    pub is_share: bool,
42    
43    /// Token 风格(uuid、simple-uuid、random-32、random-64、random-128)
44    pub token_style: TokenStyle,
45    
46    /// 是否输出操作日志
47    pub is_log: bool,
48    
49    /// 是否从 cookie 中读取 token
50    pub is_read_cookie: bool,
51    
52    /// 是否从 header 中读取 token
53    pub is_read_header: bool,
54    
55    /// 是否从请求体中读取 token
56    pub is_read_body: bool,
57    
58    /// token 前缀(例如 "Bearer ")
59    pub token_prefix: Option<String>,
60    
61    /// JWT 密钥(如果使用 JWT)
62    pub jwt_secret_key: Option<String>,
63    
64    /// JWT 算法(默认 HS256)
65    pub jwt_algorithm: Option<String>,
66    
67    /// JWT 签发者
68    pub jwt_issuer: Option<String>,
69    
70    /// JWT 受众
71    pub jwt_audience: Option<String>,
72    
73    /// 是否启用防重放攻击(nonce 机制)
74    pub enable_nonce: bool,
75    
76    /// Nonce 有效期(秒),-1 表示使用 token timeout
77    pub nonce_timeout: i64,
78    
79    /// 是否启用 Refresh Token
80    pub enable_refresh_token: bool,
81    
82    /// Refresh Token 有效期(秒),默认 7 天
83    pub refresh_token_timeout: i64,
84}
85
86impl Default for SaTokenConfig {
87    fn default() -> Self {
88        Self {
89            token_name: "sa-token".to_string(),
90            timeout: 2592000, // 30天
91            active_timeout: -1,
92            auto_renew: false, // 默认不开启自动续签
93            is_concurrent: true,
94            is_share: true,
95            token_style: TokenStyle::Uuid,
96            is_log: false,
97            is_read_cookie: true,
98            is_read_header: true,
99            is_read_body: false,
100            token_prefix: None,
101            jwt_secret_key: None,
102            jwt_algorithm: Some("HS256".to_string()),
103            jwt_issuer: None,
104            jwt_audience: None,
105            enable_nonce: false,
106            nonce_timeout: -1,
107            enable_refresh_token: false,
108            refresh_token_timeout: 604800, // 7 天
109        }
110    }
111}
112
113impl SaTokenConfig {
114    pub fn builder() -> SaTokenConfigBuilder {
115        SaTokenConfigBuilder::default()
116    }
117    
118    pub fn timeout_duration(&self) -> Option<Duration> {
119        if self.timeout < 0 {
120            None
121        } else {
122            Some(Duration::from_secs(self.timeout as u64))
123        }
124    }
125}
126
127/// Token 风格 | Token Style
128#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
129pub enum TokenStyle {
130    /// UUID 风格 | UUID style
131    Uuid,
132    /// 简化的 UUID(去掉横杠)| Simple UUID (without hyphens)
133    SimpleUuid,
134    /// 32位随机字符串 | 32-character random string
135    Random32,
136    /// 64位随机字符串 | 64-character random string
137    Random64,
138    /// 128位随机字符串 | 128-character random string
139    Random128,
140    /// JWT 风格(JSON Web Token)| JWT style (JSON Web Token)
141    Jwt,
142    /// Hash 风格(SHA256哈希)| Hash style (SHA256 hash)
143    Hash,
144    /// 时间戳风格(毫秒级时间戳+随机数)| Timestamp style (millisecond timestamp + random)
145    Timestamp,
146    /// Tik 风格(短小精悍的8位字符)| Tik style (short 8-character token)
147    Tik,
148}
149
150/// 配置构建器
151#[derive(Default)]
152pub struct SaTokenConfigBuilder {
153    config: SaTokenConfig,
154    storage: Option<Arc<dyn SaStorage>>,
155    listeners: Vec<Arc<dyn SaTokenListener>>,
156}
157
158
159impl SaTokenConfigBuilder {
160    pub fn token_name(mut self, name: impl Into<String>) -> Self {
161        self.config.token_name = name.into();
162        self
163    }
164    
165    pub fn timeout(mut self, timeout: i64) -> Self {
166        self.config.timeout = timeout;
167        self
168    }
169    
170    pub fn active_timeout(mut self, timeout: i64) -> Self {
171        self.config.active_timeout = timeout;
172        self
173    }
174    
175    /// 设置是否开启自动续签
176    pub fn auto_renew(mut self, enabled: bool) -> Self {
177        self.config.auto_renew = enabled;
178        self
179    }
180    
181    pub fn is_concurrent(mut self, concurrent: bool) -> Self {
182        self.config.is_concurrent = concurrent;
183        self
184    }
185    
186    pub fn is_share(mut self, share: bool) -> Self {
187        self.config.is_share = share;
188        self
189    }
190    
191    pub fn token_style(mut self, style: TokenStyle) -> Self {
192        self.config.token_style = style;
193        self
194    }
195    
196    pub fn token_prefix(mut self, prefix: impl Into<String>) -> Self {
197        self.config.token_prefix = Some(prefix.into());
198        self
199    }
200    
201    pub fn jwt_secret_key(mut self, key: impl Into<String>) -> Self {
202        self.config.jwt_secret_key = Some(key.into());
203        self
204    }
205    
206    /// 设置 JWT 算法
207    pub fn jwt_algorithm(mut self, algorithm: impl Into<String>) -> Self {
208        self.config.jwt_algorithm = Some(algorithm.into());
209        self
210    }
211    
212    /// 设置 JWT 签发者
213    pub fn jwt_issuer(mut self, issuer: impl Into<String>) -> Self {
214        self.config.jwt_issuer = Some(issuer.into());
215        self
216    }
217    
218    /// 设置 JWT 受众
219    pub fn jwt_audience(mut self, audience: impl Into<String>) -> Self {
220        self.config.jwt_audience = Some(audience.into());
221        self
222    }
223    
224    /// 启用防重放攻击(nonce 机制)
225    pub fn enable_nonce(mut self, enable: bool) -> Self {
226        self.config.enable_nonce = enable;
227        self
228    }
229    
230    /// 设置 Nonce 有效期(秒)
231    pub fn nonce_timeout(mut self, timeout: i64) -> Self {
232        self.config.nonce_timeout = timeout;
233        self
234    }
235    
236    /// 启用 Refresh Token
237    pub fn enable_refresh_token(mut self, enable: bool) -> Self {
238        self.config.enable_refresh_token = enable;
239        self
240    }
241    
242    /// 设置 Refresh Token 有效期(秒)
243    pub fn refresh_token_timeout(mut self, timeout: i64) -> Self {
244        self.config.refresh_token_timeout = timeout;
245        self
246    }
247    
248    /// 设置存储方式
249    pub fn storage(mut self, storage: Arc<dyn SaStorage>) -> Self {
250        self.storage = Some(storage);
251        self
252    }
253    
254    /// 注册事件监听器
255    /// 
256    /// 可以多次调用以注册多个监听器
257    /// 
258    /// # 示例
259    /// ```rust,ignore
260    /// use std::sync::Arc;
261    /// use sa_token_core::{SaTokenConfig, SaTokenListener};
262    /// 
263    /// struct MyListener;
264    /// impl SaTokenListener for MyListener { /* ... */ }
265    /// 
266    /// let manager = SaTokenConfig::builder()
267    ///     .storage(Arc::new(MemoryStorage::new()))
268    ///     .register_listener(Arc::new(MyListener))
269    ///     .build();
270    /// ```
271    pub fn register_listener(mut self, listener: Arc<dyn SaTokenListener>) -> Self {
272        self.listeners.push(listener);
273        self
274    }
275    
276    /// 构建 SaTokenManager(需要先设置 storage)
277    /// 
278    /// 自动完成以下操作:
279    /// 1. 创建 SaTokenManager
280    /// 2. 注册所有事件监听器
281    /// 3. 初始化 StpUtil
282    /// 
283    /// Auto-complete the following operations:
284    /// 1. Create SaTokenManager
285    /// 2. Register all event listeners
286    /// 3. Initialize StpUtil
287    /// 
288    /// # Panics
289    /// 如果未设置 storage,会 panic
290    /// 
291    /// # 示例
292    /// ```rust,ignore
293    /// use std::sync::Arc;
294    /// use sa_token_core::SaTokenConfig;
295    /// use sa_token_storage_memory::MemoryStorage;
296    /// 
297    /// // 一行代码完成所有初始化!
298    /// // Complete all initialization in one line!
299    /// SaTokenConfig::builder()
300    ///     .storage(Arc::new(MemoryStorage::new()))
301    ///     .timeout(7200)
302    ///     .register_listener(Arc::new(MyListener))
303    ///     .build();  // 自动初始化 StpUtil!
304    /// ```
305    pub fn build(self) -> crate::SaTokenManager {
306        let storage = self.storage.expect("Storage must be set before building SaTokenManager. Use .storage() method.");
307        let manager = crate::SaTokenManager::new(storage, self.config);
308        
309        // 同步注册所有监听器
310        // Register all listeners synchronously
311        if !self.listeners.is_empty() {
312            let event_bus = manager.event_bus();
313            for listener in self.listeners {
314                event_bus.register(listener);
315            }
316        }
317        
318        // 自动初始化 StpUtil
319        // Auto-initialize StpUtil
320        crate::StpUtil::init_manager(manager.clone());
321        
322        manager
323    }
324    
325    /// 仅构建配置(不创建 Manager)
326    pub fn build_config(self) -> SaTokenConfig {
327        self.config
328    }
329}