sa_token_core/
util.rs

1// Author: 金书记
2//
3//! StpUtil - sa-token 便捷工具类
4//! 
5//! 提供类似 Java 版 StpUtil 的静态方法,方便进行认证和权限操作
6//! 
7//! ## 使用示例
8//! 
9//! ```rust,ignore
10//! use sa_token_core::StpUtil;
11//! 
12//! // 初始化全局 Manager(应用启动时调用一次)
13//! StpUtil::init_manager(manager);
14//! 
15//! // 之后就可以直接使用,支持多种 ID 类型
16//! let token = StpUtil::login("user_123").await?;  // 字符串 ID
17//! let token = StpUtil::login(10001).await?;       // 数字 ID (i32)
18//! let token = StpUtil::login(10001_i64).await?;   // 数字 ID (i64)
19//! 
20//! StpUtil::set_permissions(10001, vec!["user:list".to_string()]).await?;
21//! ```
22
23use std::sync::Arc;
24use std::fmt::Display;
25use once_cell::sync::OnceCell;
26use crate::{SaTokenManager, SaTokenResult, SaTokenError};
27use crate::token::{TokenValue, TokenInfo};
28use crate::session::SaSession;
29use crate::context::SaTokenContext;
30use crate::event::{SaTokenEventBus, SaTokenListener};
31
32/// 全局 SaTokenManager 实例
33static GLOBAL_MANAGER: OnceCell<Arc<SaTokenManager>> = OnceCell::new();
34
35/// LoginId trait - 支持任何可以转换为字符串的类型作为登录 ID
36/// 
37/// 自动实现了 String, &str, i32, i64, u32, u64 等常用类型
38pub trait LoginId {
39    fn to_login_id(&self) -> String;
40}
41
42// 为所有实现了 Display 的类型自动实现 LoginId
43impl<T: Display> LoginId for T {
44    fn to_login_id(&self) -> String {
45        self.to_string()
46    }
47}
48
49/// StpUtil - 权限认证工具类
50/// 
51/// 提供便捷的认证和授权操作方法,类似于 Java 版 sa-token 的 StpUtil
52pub struct StpUtil;
53
54impl StpUtil {
55    // ==================== 初始化 ====================
56    
57    /// 初始化全局 SaTokenManager(应用启动时调用一次)
58    /// 
59    /// # 示例
60    /// ```rust,ignore
61    /// let manager = SaTokenConfig::builder()
62    ///     .storage(Arc::new(MemoryStorage::new()))
63    ///     .build();
64    /// StpUtil::init_manager(manager);
65    /// ```
66    pub fn init_manager(manager: SaTokenManager) {
67        GLOBAL_MANAGER.set(Arc::new(manager))
68            .unwrap_or_else(|_| panic!("StpUtil manager already initialized"));
69    }
70    
71    /// 获取全局 Manager
72    fn get_manager() -> &'static Arc<SaTokenManager> {
73        GLOBAL_MANAGER.get()
74            .expect("StpUtil not initialized. Call StpUtil::init_manager() first.")
75    }
76    
77    /// 获取事件总线,用于注册监听器
78    /// 
79    /// # 示例
80    /// ```rust,ignore
81    /// use sa_token_core::{StpUtil, SaTokenListener};
82    /// use async_trait::async_trait;
83    /// 
84    /// struct MyListener;
85    /// 
86    /// #[async_trait]
87    /// impl SaTokenListener for MyListener {
88    ///     async fn on_login(&self, login_id: &str, token: &str, login_type: &str) {
89    ///         println!("用户 {} 登录了", login_id);
90    ///     }
91    /// }
92    /// 
93    /// // 注册监听器
94    /// StpUtil::event_bus().register(Arc::new(MyListener)).await;
95    /// ```
96    pub fn event_bus() -> &'static SaTokenEventBus {
97        &Self::get_manager().event_bus
98    }
99    
100    /// 注册事件监听器(便捷方法)
101    /// 
102    /// # 示例
103    /// ```rust,ignore
104    /// StpUtil::register_listener(Arc::new(MyListener)).await;
105    /// ```
106    pub fn register_listener(listener: Arc<dyn SaTokenListener>) {
107        Self::event_bus().register(listener);
108    }
109    
110    // ==================== 登录相关 ====================
111    
112    /// 会话登录
113    /// 
114    /// # 示例
115    /// ```rust,ignore
116    /// // 支持字符串 ID
117    /// let token = StpUtil::login("user_123").await?;
118    /// 
119    /// // 支持数字 ID
120    /// let token = StpUtil::login(10001).await?;
121    /// let token = StpUtil::login(10001_i64).await?;
122    /// ```
123    pub async fn login(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
124        Self::get_manager().login(login_id.to_login_id()).await
125    }
126    
127    /// 登录并设置额外数据 | Login with extra data
128    /// 
129    /// # 参数 | Arguments
130    /// * `login_id` - 登录ID | Login ID
131    /// * `extra_data` - 额外数据 | Extra data
132    pub async fn login_with_extra(
133        login_id: impl LoginId,
134        extra_data: serde_json::Value,
135    ) -> SaTokenResult<TokenValue> {
136        let token = Self::get_manager().login(login_id.to_login_id()).await?;
137        Self::set_extra_data(&token, extra_data).await?;
138        Ok(token)
139    }
140    
141    /// 会话登录(带 manager 参数的版本,向后兼容)
142    pub async fn login_with_manager(
143        manager: &SaTokenManager,
144        login_id: impl Into<String>,
145    ) -> SaTokenResult<TokenValue> {
146        manager.login(login_id).await
147    }
148    
149    /// 会话登出
150    pub async fn logout(token: &TokenValue) -> SaTokenResult<()> {
151        Self::get_manager().logout(token).await
152    }
153    
154    pub async fn logout_with_manager(
155        manager: &SaTokenManager,
156        token: &TokenValue,
157    ) -> SaTokenResult<()> {
158        manager.logout(token).await
159    }
160    
161    /// 踢人下线(根据登录ID)
162    pub async fn kick_out(login_id: impl LoginId) -> SaTokenResult<()> {
163        Self::get_manager().kick_out(&login_id.to_login_id()).await
164    }
165    
166    pub async fn kick_out_with_manager(
167        manager: &SaTokenManager,
168        login_id: &str,
169    ) -> SaTokenResult<()> {
170        manager.kick_out(login_id).await
171    }
172    
173    /// 强制登出(根据登录ID)
174    pub async fn logout_by_login_id(login_id: impl LoginId) -> SaTokenResult<()> {
175        Self::get_manager().logout_by_login_id(&login_id.to_login_id()).await
176    }
177    
178    /// 根据 token 登出(别名方法,更直观)
179    pub async fn logout_by_token(token: &TokenValue) -> SaTokenResult<()> {
180        Self::logout(token).await
181    }
182    
183    // ==================== 当前会话操作(无参数,从上下文获取)====================
184    
185    /// 获取当前请求的 token(无参数,从上下文获取)
186    /// 
187    /// # 示例
188    /// ```rust,ignore
189    /// // 在请求处理函数中
190    /// let token = StpUtil::get_token_value()?;
191    /// ```
192    pub fn get_token_value() -> SaTokenResult<TokenValue> {
193        let ctx = SaTokenContext::get_current()
194            .ok_or(SaTokenError::NotLogin)?;
195        ctx.token.ok_or(SaTokenError::NotLogin)
196    }
197    
198    /// 当前会话登出(无参数,从上下文获取 token)
199    /// 
200    /// # 示例
201    /// ```rust,ignore
202    /// // 在请求处理函数中
203    /// StpUtil::logout_current().await?;
204    /// ```
205    pub async fn logout_current() -> SaTokenResult<()> {
206        let token = Self::get_token_value()?;
207        Self::logout(&token).await
208    }
209    
210    /// 检查当前会话是否登录(无参数,返回 bool)
211    /// 
212    /// # 示例
213    /// ```rust,ignore
214    /// // 在请求处理函数中
215    /// if StpUtil::is_login_current() {
216    ///     println!("当前用户已登录");
217    /// }
218    /// ```
219    pub fn is_login_current() -> bool {
220        if let Ok(_token) = Self::get_token_value() {
221            // 注意:这里使用同步检查,只检查上下文中是否有 token
222            // 如果需要异步验证,需要使用 is_login(&token).await
223            true
224        } else {
225            false
226        }
227    }
228    
229    /// 检查当前会话登录状态,未登录则抛出异常(无参数)
230    /// 
231    /// # 示例
232    /// ```rust,ignore
233    /// // 在请求处理函数中
234    /// StpUtil::check_login_current()?;
235    /// ```
236    pub fn check_login_current() -> SaTokenResult<()> {
237        Self::get_token_value()?;
238        Ok(())
239    }
240    
241    /// 获取当前会话的 login_id(String 类型,无参数)
242    /// 
243    /// # 示例
244    /// ```rust,ignore
245    /// // 在请求处理函数中
246    /// let login_id = StpUtil::get_login_id_as_string()?;
247    /// ```
248    pub fn get_login_id_as_string() -> SaTokenResult<String> {
249        let ctx = SaTokenContext::get_current()
250            .ok_or(SaTokenError::NotLogin)?;
251        ctx.login_id.ok_or(SaTokenError::NotLogin)
252    }
253    
254    /// 获取当前会话的 login_id(i64 类型,无参数)
255    /// 
256    /// # 示例
257    /// ```rust,ignore
258    /// // 在请求处理函数中
259    /// let user_id = StpUtil::get_login_id_as_long()?;
260    /// ```
261    pub fn get_login_id_as_long() -> SaTokenResult<i64> {
262        let login_id_str = Self::get_login_id_as_string()?;
263        login_id_str.parse::<i64>()
264            .map_err(|_| SaTokenError::LoginIdNotNumber)
265    }
266    
267    /// 获取当前会话的 token 信息(无参数)
268    /// 
269    /// # 示例
270    /// ```rust,ignore
271    /// // 在请求处理函数中
272    /// let token_info = StpUtil::get_token_info_current()?;
273    /// println!("Token 创建时间: {:?}", token_info.create_time);
274    /// ```
275    pub fn get_token_info_current() -> SaTokenResult<Arc<TokenInfo>> {
276        let ctx = SaTokenContext::get_current()
277            .ok_or(SaTokenError::NotLogin)?;
278        ctx.token_info.ok_or(SaTokenError::NotLogin)
279    }
280    
281    // ==================== Token 验证 ====================
282    
283    /// 检查当前 token 是否已登录
284    pub async fn is_login(token: &TokenValue) -> bool {
285        Self::get_manager().is_valid(token).await
286    }
287    
288    /// 根据登录 ID 检查是否已登录
289    /// 
290    /// # 示例
291    /// ```rust,ignore
292    /// let is_logged_in = StpUtil::is_login_by_login_id("user_123").await;
293    /// let is_logged_in = StpUtil::is_login_by_login_id(10001).await;
294    /// ```
295    pub async fn is_login_by_login_id(login_id: impl LoginId) -> bool {
296        match Self::get_token_by_login_id(login_id).await {
297            Ok(token) => Self::is_login(&token).await,
298            Err(_) => false,
299        }
300    }
301    
302    pub async fn is_login_with_manager(
303        manager: &SaTokenManager,
304        token: &TokenValue,
305    ) -> bool {
306        manager.is_valid(token).await
307    }
308    
309    /// 检查当前 token 是否已登录,如果未登录则抛出异常
310    pub async fn check_login(token: &TokenValue) -> SaTokenResult<()> {
311        if !Self::is_login(token).await {
312            return Err(SaTokenError::NotLogin);
313        }
314        Ok(())
315    }
316    
317    /// 获取 token 信息
318    pub async fn get_token_info(token: &TokenValue) -> SaTokenResult<TokenInfo> {
319        Self::get_manager().get_token_info(token).await
320    }
321    
322    /// 获取当前 token 的登录ID
323    pub async fn get_login_id(token: &TokenValue) -> SaTokenResult<String> {
324        let token_info = Self::get_manager().get_token_info(token).await?;
325        Ok(token_info.login_id)
326    }
327    
328    /// 获取当前 token 的登录ID,如果未登录则返回默认值
329    pub async fn get_login_id_or_default(
330        token: &TokenValue,
331        default: impl Into<String>,
332    ) -> String {
333        Self::get_login_id(token)
334            .await
335            .unwrap_or_else(|_| default.into())
336    }
337    
338    /// 根据登录 ID 获取当前用户的 token
339    /// 
340    /// # 示例
341    /// ```rust,ignore
342    /// let token = StpUtil::get_token_by_login_id("user_123").await?;
343    /// let token = StpUtil::get_token_by_login_id(10001).await?;
344    /// ```
345    pub async fn get_token_by_login_id(login_id: impl LoginId) -> SaTokenResult<TokenValue> {
346        let manager = Self::get_manager();
347        let login_id_str = login_id.to_login_id();
348        
349        // 从存储中获取该用户的 token
350        let key = format!("sa:login:token:{}", login_id_str);
351        match manager.storage.get(&key).await {
352            Ok(Some(token_str)) => Ok(TokenValue::new(token_str)),
353            Ok(None) => Err(SaTokenError::NotLogin),
354            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
355        }
356    }
357    
358    /// 根据登录 ID 获取所有在线的 token 列表(支持多设备登录)
359    /// 
360    /// # 示例
361    /// ```rust,ignore
362    /// let tokens = StpUtil::get_all_tokens_by_login_id("user_123").await?;
363    /// ```
364    pub async fn get_all_tokens_by_login_id(login_id: impl LoginId) -> SaTokenResult<Vec<TokenValue>> {
365        let manager = Self::get_manager();
366        let login_id_str = login_id.to_login_id();
367        
368        // 从存储中获取该用户的所有 token
369        let key = format!("sa:login:tokens:{}", login_id_str);
370        match manager.storage.get(&key).await {
371            Ok(Some(tokens_str)) => {
372                let token_strings: Vec<String> = serde_json::from_str(&tokens_str)
373                    .map_err(|e| SaTokenError::SerializationError(e))?;
374                Ok(token_strings.into_iter().map(TokenValue::new).collect())
375            }
376            Ok(None) => Ok(Vec::new()),
377            Err(e) => Err(SaTokenError::StorageError(e.to_string())),
378        }
379    }
380    
381    // ==================== Session 会话 ====================
382    
383    /// 获取当前登录账号的 Session
384    pub async fn get_session(login_id: impl LoginId) -> SaTokenResult<SaSession> {
385        Self::get_manager().get_session(&login_id.to_login_id()).await
386    }
387    
388    /// 保存 Session
389    pub async fn save_session(session: &SaSession) -> SaTokenResult<()> {
390        Self::get_manager().save_session(session).await
391    }
392    
393    /// 删除 Session
394    pub async fn delete_session(login_id: impl LoginId) -> SaTokenResult<()> {
395        Self::get_manager().delete_session(&login_id.to_login_id()).await
396    }
397    
398    /// 在 Session 中设置值
399    pub async fn set_session_value<T: serde::Serialize>(
400        login_id: impl LoginId,
401        key: &str,
402        value: T,
403    ) -> SaTokenResult<()> {
404        let manager = Self::get_manager();
405        let login_id_str = login_id.to_login_id();
406        let mut session = manager.get_session(&login_id_str).await?;
407        session.set(key, value)?;
408        manager.save_session(&session).await
409    }
410    
411    /// 从 Session 中获取值
412    pub async fn get_session_value<T: serde::de::DeserializeOwned>(
413        login_id: impl LoginId,
414        key: &str,
415    ) -> SaTokenResult<Option<T>> {
416        let session = Self::get_manager().get_session(&login_id.to_login_id()).await?;
417        Ok(session.get::<T>(key))
418    }
419    
420    // ==================== Token 相关 ====================
421    
422    /// 创建一个新的 token(但不登录)
423    pub fn create_token(token_value: impl Into<String>) -> TokenValue {
424        TokenValue::new(token_value.into())
425    }
426    
427    /// 检查 token 格式是否有效(仅检查格式,不检查是否存在于存储中)
428    pub fn is_valid_token_format(token: &str) -> bool {
429        !token.is_empty() && token.len() >= 16
430    }
431}
432
433// ==================== 权限管理 ====================
434
435impl StpUtil {
436    /// 为用户添加权限
437    pub async fn set_permissions(
438        login_id: impl LoginId,
439        permissions: Vec<String>,
440    ) -> SaTokenResult<()> {
441        let manager = Self::get_manager();
442        let mut map = manager.user_permissions.write().await;
443        map.insert(login_id.to_login_id(), permissions);
444        Ok(())
445    }
446    
447    /// 为用户添加单个权限
448    pub async fn add_permission(
449        login_id: impl LoginId,
450        permission: impl Into<String>,
451    ) -> SaTokenResult<()> {
452        let manager = Self::get_manager();
453        let mut map = manager.user_permissions.write().await;
454        let login_id_str = login_id.to_login_id();
455        let permissions = map.entry(login_id_str).or_insert_with(Vec::new);
456        let perm = permission.into();
457        if !permissions.contains(&perm) {
458            permissions.push(perm);
459        }
460        Ok(())
461    }
462    
463    /// 移除用户的某个权限
464    pub async fn remove_permission(
465        login_id: impl LoginId,
466        permission: &str,
467    ) -> SaTokenResult<()> {
468        let manager = Self::get_manager();
469        let mut map = manager.user_permissions.write().await;
470        if let Some(permissions) = map.get_mut(&login_id.to_login_id()) {
471            permissions.retain(|p| p != permission);
472        }
473        Ok(())
474    }
475    
476    /// 清除用户的所有权限
477    pub async fn clear_permissions(login_id: impl LoginId) -> SaTokenResult<()> {
478        let manager = Self::get_manager();
479        let mut map = manager.user_permissions.write().await;
480        map.remove(&login_id.to_login_id());
481        Ok(())
482    }
483    
484    /// 获取用户的所有权限
485    pub async fn get_permissions(login_id: impl LoginId) -> Vec<String> {
486        let manager = Self::get_manager();
487        let map = manager.user_permissions.read().await;
488        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
489    }
490    
491    /// 检查用户是否拥有指定权限
492    pub async fn has_permission(
493        login_id: impl LoginId,
494        permission: &str,
495    ) -> bool {
496        let manager = Self::get_manager();
497        let map = manager.user_permissions.read().await;
498        if let Some(permissions) = map.get(&login_id.to_login_id()) {
499            // 精确匹配
500            if permissions.contains(&permission.to_string()) {
501                return true;
502            }
503            
504            // 通配符匹配(例如 admin:* 匹配 admin:read)
505            for perm in permissions {
506                if perm.ends_with(":*") {
507                    let prefix = &perm[..perm.len() - 2];
508                    if permission.starts_with(prefix) {
509                        return true;
510                    }
511                }
512            }
513        }
514        false
515    }
516    
517    /// 检查用户是否拥有所有指定权限(AND 逻辑)
518    pub async fn has_all_permissions(
519        login_id: impl LoginId,
520        permissions: &[&str],
521    ) -> bool {
522        let login_id_str = login_id.to_login_id();
523        for permission in permissions {
524            if !Self::has_permission(&login_id_str, permission).await {
525                return false;
526            }
527        }
528        true
529    }
530    
531    /// 检查用户是否拥有所有指定权限(别名,AND 逻辑)
532    pub async fn has_permissions_and(
533        login_id: impl LoginId,
534        permissions: &[&str],
535    ) -> bool {
536        Self::has_all_permissions(login_id, permissions).await
537    }
538    
539    /// 检查用户是否拥有任一指定权限(OR 逻辑)
540    pub async fn has_any_permission(
541        login_id: impl LoginId,
542        permissions: &[&str],
543    ) -> bool {
544        let login_id_str = login_id.to_login_id();
545        for permission in permissions {
546            if Self::has_permission(&login_id_str, permission).await {
547                return true;
548            }
549        }
550        false
551    }
552    
553    /// 检查用户是否拥有任一指定权限(别名,OR 逻辑)
554    pub async fn has_permissions_or(
555        login_id: impl LoginId,
556        permissions: &[&str],
557    ) -> bool {
558        Self::has_any_permission(login_id, permissions).await
559    }
560    
561    /// 检查权限,如果没有则抛出异常
562    pub async fn check_permission(
563        login_id: impl LoginId,
564        permission: &str,
565    ) -> SaTokenResult<()> {
566        if !Self::has_permission(login_id, permission).await {
567            return Err(SaTokenError::PermissionDeniedDetail(permission.to_string()));
568        }
569        Ok(())
570    }
571}
572
573// ==================== 角色管理 ====================
574
575impl StpUtil {
576    /// 为用户设置角色
577    pub async fn set_roles(
578        login_id: impl LoginId,
579        roles: Vec<String>,
580    ) -> SaTokenResult<()> {
581        let manager = Self::get_manager();
582        let mut map = manager.user_roles.write().await;
583        map.insert(login_id.to_login_id(), roles);
584        Ok(())
585    }
586    
587    /// 为用户添加单个角色
588    pub async fn add_role(
589        login_id: impl LoginId,
590        role: impl Into<String>,
591    ) -> SaTokenResult<()> {
592        let manager = Self::get_manager();
593        let mut map = manager.user_roles.write().await;
594        let login_id_str = login_id.to_login_id();
595        let roles = map.entry(login_id_str).or_insert_with(Vec::new);
596        let r = role.into();
597        if !roles.contains(&r) {
598            roles.push(r);
599        }
600        Ok(())
601    }
602    
603    /// 移除用户的某个角色
604    pub async fn remove_role(
605        login_id: impl LoginId,
606        role: &str,
607    ) -> SaTokenResult<()> {
608        let manager = Self::get_manager();
609        let mut map = manager.user_roles.write().await;
610        if let Some(roles) = map.get_mut(&login_id.to_login_id()) {
611            roles.retain(|r| r != role);
612        }
613        Ok(())
614    }
615    
616    /// 清除用户的所有角色
617    pub async fn clear_roles(login_id: impl LoginId) -> SaTokenResult<()> {
618        let manager = Self::get_manager();
619        let mut map = manager.user_roles.write().await;
620        map.remove(&login_id.to_login_id());
621        Ok(())
622    }
623    
624    /// 获取用户的所有角色
625    pub async fn get_roles(login_id: impl LoginId) -> Vec<String> {
626        let manager = Self::get_manager();
627        let map = manager.user_roles.read().await;
628        map.get(&login_id.to_login_id()).cloned().unwrap_or_default()
629    }
630    
631    /// 检查用户是否拥有指定角色
632    pub async fn has_role(
633        login_id: impl LoginId,
634        role: &str,
635    ) -> bool {
636        let manager = Self::get_manager();
637        let map = manager.user_roles.read().await;
638        if let Some(roles) = map.get(&login_id.to_login_id()) {
639            roles.contains(&role.to_string())
640        } else {
641            false
642        }
643    }
644    
645    /// 检查用户是否拥有所有指定角色(AND 逻辑)
646    pub async fn has_all_roles(
647        login_id: impl LoginId,
648        roles: &[&str],
649    ) -> bool {
650        let login_id_str = login_id.to_login_id();
651        for role in roles {
652            if !Self::has_role(&login_id_str, role).await {
653                return false;
654            }
655        }
656        true
657    }
658    
659    /// 检查用户是否拥有所有指定角色(别名,AND 逻辑)
660    pub async fn has_roles_and(
661        login_id: impl LoginId,
662        roles: &[&str],
663    ) -> bool {
664        Self::has_all_roles(login_id, roles).await
665    }
666    
667    /// 检查用户是否拥有任一指定角色(OR 逻辑)
668    pub async fn has_any_role(
669        login_id: impl LoginId,
670        roles: &[&str],
671    ) -> bool {
672        let login_id_str = login_id.to_login_id();
673        for role in roles {
674            if Self::has_role(&login_id_str, role).await {
675                return true;
676            }
677        }
678        false
679    }
680    
681    /// 检查用户是否拥有任一指定角色(别名,OR 逻辑)
682    pub async fn has_roles_or(
683        login_id: impl LoginId,
684        roles: &[&str],
685    ) -> bool {
686        Self::has_any_role(login_id, roles).await
687    }
688    
689    /// 检查角色,如果没有则抛出异常
690    pub async fn check_role(
691        login_id: impl LoginId,
692        role: &str,
693    ) -> SaTokenResult<()> {
694        if !Self::has_role(login_id, role).await {
695            return Err(SaTokenError::RoleDenied(role.to_string()));
696        }
697        Ok(())
698    }
699}
700
701// ==================== 扩展工具方法 ====================
702
703impl StpUtil {
704    /// 批量踢人下线
705    pub async fn kick_out_batch<T: LoginId>(
706        login_ids: &[T],
707    ) -> SaTokenResult<Vec<Result<(), SaTokenError>>> {
708        let manager = Self::get_manager();
709        let mut results = Vec::new();
710        for login_id in login_ids {
711            results.push(manager.kick_out(&login_id.to_login_id()).await);
712        }
713        Ok(results)
714    }
715    
716    /// 获取 token 剩余有效时间(秒)
717    pub async fn get_token_timeout(token: &TokenValue) -> SaTokenResult<Option<i64>> {
718        let manager = Self::get_manager();
719        let token_info = manager.get_token_info(token).await?;
720        
721        if let Some(expire_time) = token_info.expire_time {
722            let now = chrono::Utc::now();
723            let duration = expire_time.signed_duration_since(now);
724            Ok(Some(duration.num_seconds()))
725        } else {
726            Ok(None) // 永久有效
727        }
728    }
729    
730    /// 续期 token(重置过期时间)
731    pub async fn renew_timeout(
732        token: &TokenValue,
733        timeout_seconds: i64,
734    ) -> SaTokenResult<()> {
735        let manager = Self::get_manager();
736        let mut token_info = manager.get_token_info(token).await?;
737        
738        // 设置新的过期时间
739        let new_expire_time = chrono::Utc::now() + chrono::Duration::seconds(timeout_seconds);
740        token_info.expire_time = Some(new_expire_time);
741        
742        // 保存更新后的 token 信息
743        let key = format!("sa:token:{}", token.as_str());
744        let value = serde_json::to_string(&token_info)
745            .map_err(|e| SaTokenError::SerializationError(e))?;
746        
747        let timeout = std::time::Duration::from_secs(timeout_seconds as u64);
748        manager.storage.set(&key, &value, Some(timeout)).await
749            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
750        
751        Ok(())
752    }
753    
754    // ==================== 额外数据操作 | Extra Data Operations ====================
755    
756    /// 设置 Token 的额外数据 | Set extra data for token
757    /// 
758    /// # 参数 | Arguments
759    /// * `token` - Token值 | Token value
760    /// * `extra_data` - 额外数据 | Extra data
761    pub async fn set_extra_data(
762        token: &TokenValue,
763        extra_data: serde_json::Value,
764    ) -> SaTokenResult<()> {
765        let manager = Self::get_manager();
766        let mut token_info = manager.get_token_info(token).await?;
767        token_info.extra_data = Some(extra_data);
768        
769        let key = format!("sa:token:{}", token.as_str());
770        let value = serde_json::to_string(&token_info)
771            .map_err(|e| SaTokenError::SerializationError(e))?;
772        
773        manager.storage.set(&key, &value, manager.config.timeout_duration()).await
774            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
775        
776        Ok(())
777    }
778    
779    /// 获取 Token 的额外数据 | Get extra data from token
780    /// 
781    /// # 参数 | Arguments
782    /// * `token` - Token值 | Token value
783    pub async fn get_extra_data(token: &TokenValue) -> SaTokenResult<Option<serde_json::Value>> {
784        let manager = Self::get_manager();
785        let token_info = manager.get_token_info(token).await?;
786        Ok(token_info.extra_data)
787    }
788    
789    // ==================== 链式调用 | Chain Call ====================
790    
791    /// 创建 Token 构建器,用于链式调用 | Create token builder for chain calls
792    /// 
793    /// # 示例 | Example
794    /// ```rust,ignore
795    /// use serde_json::json;
796    /// 
797    /// // 链式调用示例
798    /// let token = StpUtil::builder("user_123")
799    ///     .extra_data(json!({"ip": "192.168.1.1"}))
800    ///     .device("pc")
801    ///     .login_type("admin")
802    ///     .login()
803    ///     .await?;
804    /// ```
805    pub fn builder(login_id: impl LoginId) -> TokenBuilder {
806        TokenBuilder::new(login_id.to_login_id())
807    }
808}
809
810/// Token 构建器 - 支持链式调用 | Token Builder - Supports chain calls
811pub struct TokenBuilder {
812    login_id: String,
813    extra_data: Option<serde_json::Value>,
814    device: Option<String>,
815    login_type: Option<String>,
816}
817
818impl TokenBuilder {
819    /// 创建新的 Token 构建器 | Create new token builder
820    pub fn new(login_id: String) -> Self {
821        Self {
822            login_id,
823            extra_data: None,
824            device: None,
825            login_type: None,
826        }
827    }
828    
829    /// 设置额外数据 | Set extra data
830    pub fn extra_data(mut self, data: serde_json::Value) -> Self {
831        self.extra_data = Some(data);
832        self
833    }
834    
835    /// 设置设备信息 | Set device info
836    pub fn device(mut self, device: impl Into<String>) -> Self {
837        self.device = Some(device.into());
838        self
839    }
840    
841    /// 设置登录类型 | Set login type
842    pub fn login_type(mut self, login_type: impl Into<String>) -> Self {
843        self.login_type = Some(login_type.into());
844        self
845    }
846    
847    /// 执行登录操作 | Execute login
848    /// 
849    /// 如果不提供 login_id 参数,则使用构建器中的 login_id
850    pub async fn login<T: LoginId>(self, login_id: Option<T>) -> SaTokenResult<TokenValue> {
851        let manager = StpUtil::get_manager();
852        
853        // 登录获取 token,使用传入的 login_id 或构建器中的 login_id
854        let final_login_id = match login_id {
855            Some(id) => id.to_login_id(),
856            None => self.login_id,
857        };
858        let token = manager.login(final_login_id).await?;
859        
860        // 获取 token 信息并修改
861        let mut token_info = manager.get_token_info(&token).await?;
862        
863        // 设置额外属性
864        if let Some(data) = self.extra_data {
865            token_info.extra_data = Some(data);
866        }
867        
868        if let Some(device) = self.device {
869            token_info.device = Some(device);
870        }
871        
872        if let Some(login_type) = self.login_type {
873            token_info.login_type = login_type;
874        }
875        
876        // 保存更新后的 token 信息
877        let key = format!("sa:token:{}", token.as_str());
878        let value = serde_json::to_string(&token_info)
879            .map_err(|e| SaTokenError::SerializationError(e))?;
880        
881        manager.storage.set(&key, &value, manager.config.timeout_duration()).await
882            .map_err(|e| SaTokenError::StorageError(e.to_string()))?;
883        
884        Ok(token)
885    }
886}
887
888#[cfg(test)]
889mod tests {
890    use super::*;
891    
892    #[test]
893    fn test_token_format_validation() {
894        assert!(StpUtil::is_valid_token_format("1234567890abcdef"));
895        assert!(!StpUtil::is_valid_token_format(""));
896        assert!(!StpUtil::is_valid_token_format("short"));
897    }
898    
899    #[test]
900    fn test_create_token() {
901        let token = StpUtil::create_token("test-token-123");
902        assert_eq!(token.as_str(), "test-token-123");
903    }
904}