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

Azure Function实现未过期访问令牌在后续API调用中的复用

复用外部API访问令牌的解决方案

核心思路是缓存令牌并验证过期状态,同时保证并发场景下的线程安全,避免重复获取令牌。以下是具体实现步骤和代码示例:

1. 定义令牌相关模型

首先创建存储令牌和过期时间的模型,以及外部API返回的令牌响应模型:

// 缓存用的令牌模型
public class CachedAccessToken
{
    public string Token { get; set; }
    public DateTime ExpiresAt { get; set; }
}

// 外部API返回的令牌响应
public class ExternalTokenResponse
{
    public string AccessToken { get; set; }
    public int ExpiresIn { get; set; } // 令牌有效期(秒)
}

2. 实现带缓存的令牌获取逻辑

在HTTP Trigger类中,使用静态变量存储缓存令牌,并用SemaphoreSlim处理异步并发场景,防止多个请求同时触发令牌获取:

public class MyHttpTrigger
{
    // 静态变量存储缓存令牌,仅在当前实例有效
    private static CachedAccessToken _cachedToken;
    // 异步锁,控制并发令牌获取
    private static readonly SemaphoreSlim _tokenLock = new SemaphoreSlim(1, 1);

    [FunctionName("MyHttpTrigger")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        // 获取有效令牌
        var validToken = await GetValidAccessTokenAsync(log);
        
        // 调用外部API
        var apiResult = await PerformExternalAPICallAsync(validToken, log);
        
        return new OkObjectResult(apiResult);
    }

    private async Task<string> GetValidAccessTokenAsync(ILogger log)
    {
        // 先检查缓存令牌是否有效(提前30秒过期,避免网络延迟导致令牌失效)
        if (_cachedToken != null && _cachedToken.ExpiresAt > DateTime.UtcNow.AddSeconds(30))
        {
            log.LogInformation("使用缓存的访问令牌");
            return _cachedToken.Token;
        }

        // 进入异步锁,防止并发请求重复获取令牌
        await _tokenLock.WaitAsync();
        try
        {
            // 双重检查:避免等待锁期间已有其他请求更新了令牌
            if (_cachedToken != null && _cachedToken.ExpiresAt > DateTime.UtcNow.AddSeconds(30))
            {
                log.LogInformation("锁检查后使用缓存的访问令牌");
                return _cachedToken.Token;
            }

            // 调用外部API获取新令牌
            log.LogInformation("获取新的访问令牌");
            var tokenResponse = await FetchAccessTokenFromExternalAPIAsync(log);
            
            // 更新缓存令牌,提前30秒设置过期时间
            _cachedToken = new CachedAccessToken
            {
                Token = tokenResponse.AccessToken,
                ExpiresAt = DateTime.UtcNow.AddSeconds(tokenResponse.ExpiresIn - 30)
            };

            return _cachedToken.Token;
        }
        finally
        {
            // 释放锁
            _tokenLock.Release();
        }
    }

    // 调用外部API获取令牌的具体实现
    private async Task<ExternalTokenResponse> FetchAccessTokenFromExternalAPIAsync(ILogger log)
    {
        using var client = new HttpClient();
        var tokenRequest = new HttpRequestMessage(HttpMethod.Post, "https://external-api.com/oauth/token");
        
        // 客户端凭据流参数
        var formData = new Dictionary<string, string>
        {
            {"grant_type", "client_credentials"},
            {"client_id", "你的客户端ID"},
            {"client_secret", "你的客户端密钥"},
            {"scope", "所需权限范围"}
        };
        tokenRequest.Content = new FormUrlEncodedContent(formData);

        var response = await client.SendAsync(tokenRequest);
        response.EnsureSuccessStatusCode();
        
        return await response.Content.ReadFromJsonAsync<ExternalTokenResponse>();
    }

    // 调用外部业务API的具体实现
    private async Task<string> PerformExternalAPICallAsync(string token, ILogger log)
    {
        using var client = new HttpClient();
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
        
        var apiResponse = await client.GetAsync("https://external-api.com/api/目标资源");
        apiResponse.EnsureSuccessStatusCode();
        
        return await apiResponse.Content.ReadAsStringAsync();
    }
}

3. 关键注意事项

  • 线程安全:使用SemaphoreSlim替代lock,适配异步场景,避免阻塞线程池线程
  • 缓冲时间:提前30秒标记令牌过期,防止网络延迟导致令牌在请求过程中失效
  • 多实例部署:如果函数是多实例运行(如Azure Functions消耗计划),静态变量仅在单个实例内有效,此时需要改用分布式缓存(如Redis)共享令牌,所有实例统一从分布式缓存读取和更新
  • 失效重试:如果调用外部API返回401 Unauthorized,即使缓存令牌未过期,也应主动刷新令牌并重试请求(可添加Polly等重试库实现)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:10:24