You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Rust中临时存储Bearer Token并设置900秒过期

Rust中Bearer Token的临时存储与过期管理实现

核心思路

实现一个带过期校验的token缓存,核心能力包括:

  • 存储token字符串与对应过期时间戳
  • 自动判断token有效性,过期则触发重新请求
  • 保证异步环境下的线程安全访问

实现步骤

1. 定义全局异步安全的Token缓存

使用Arc<Mutex<>>实现跨任务的安全共享,结合lazy_static创建全局静态缓存实例:

use std::sync::{Arc, Mutex};
use std::time::{SystemTime, UNIX_EPOCH};
use lazy_static::lazy_static;

#[derive(Debug, Clone)]
struct TokenCache {
    access_token: Option<String>,
    expires_at: u64, // 过期时间的UNIX时间戳(秒)
}

impl TokenCache {
    fn new() -> Self {
        TokenCache {
            access_token: None,
            expires_at: 0,
        }
    }

    // 检查token是否未过期
    fn is_valid(&self) -> bool {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs();
        now < self.expires_at
    }
}

// 全局静态缓存实例
lazy_static! {
    static ref TOKEN_CACHE: Arc<Mutex<TokenCache>> = Arc::new(Mutex::new(TokenCache::new()));
}

2. 封装统一的有效Token获取函数

将token请求、缓存更新、过期校验逻辑封装到一个函数中,其他业务代码直接调用即可:

use reqwest::{Client, StatusCode};
use serde::Deserialize;
use std::collections::HashMap;

#[derive(Debug, Deserialize)]
struct SecureToken {
    access_token: String,
    expires_in: u32, // 接口返回的token有效期(秒),如果是直接返回过期时间戳可替换为expiration_date_time
}

#[derive(Debug, Deserialize)]
struct BadRequest {
    error: String,
    error_description: Option<String>,
}

async fn get_valid_token() -> Result<String, Box<dyn std::error::Error>> {
    let mut cache = TOKEN_CACHE.lock().unwrap();

    // 缓存有效直接返回
    if cache.is_valid() {
        return Ok(cache.access_token.as_ref().unwrap().clone());
    }

    // 缓存失效,请求新token
    let client = Client::new();
    let mut map = HashMap::new();
    map.insert("client_id", "your_client_id");
    map.insert("client_secret", "your_client_secret");
    map.insert("scope", "your_scope");
    map.insert("grant_type", "client_credentials");

    let token_request = client
        .post("https://gatway.address")
        .form(&map)
        .send()
        .await?;

    match token_request.status() {
        StatusCode::OK => {
            let secure_token = token_request.json::<SecureToken>().await?;
            let now = SystemTime::now()
                .duration_since(UNIX_EPOCH)
                .unwrap()
                .as_secs();
            // 提前10秒刷新,避免刚好过期的边界情况
            let expires_at = now + secure_token.expires_in as u64 - 10;

            // 更新缓存
            cache.access_token = Some(secure_token.access_token.clone());
            cache.expires_at = expires_at;

            Ok(secure_token.access_token)
        }
        StatusCode::FORBIDDEN => Err("无法连接到认证服务".into()),
        StatusCode::BAD_REQUEST => {
            let bad_request = token_request.json::<BadRequest>().await?;
            Err(format!("请求错误: {:?}", bad_request).into())
        }
        s => Err(format!("未知状态码: {:?}", s).into()),
    }
}

3. 业务代码调用示例

在需要使用token的接口请求中,直接调用get_valid_token()即可:

async fn call_protected_api() -> Result<(), Box<dyn std::error::Error>> {
    let token = get_valid_token().await?;
    let client = Client::new();

    let response = client
        .get("https://api.example.com/protected")
        .bearer_auth(token)
        .send()
        .await?;

    println!("API响应状态: {:?}", response.status());
    Ok(())
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 首次调用会请求新token
    call_protected_api().await?;
    // 短时间内再次调用使用缓存token
    call_protected_api().await?;
    Ok(())
}

依赖配置

需要在Cargo.toml中添加以下依赖:

[dependencies]
reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] }
lazy_static = "1.4"
tokio = { version = "1.0", features = ["full"] }

注意事项

  • 如果接口返回的是直接的过期时间戳(expiration_date_time),则无需计算,直接将expires_at设为该值即可
  • Arc<Mutex<>>确保异步任务间的缓存访问安全,避免数据竞争
  • 提前10秒刷新的逻辑可根据业务需求调整,避免在请求时刻刚好遇到token过期

内容的提问来源于stack exchange,提问作者LIDAR_Freak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 07:05:22