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

ASP.NET Core 6如何为AddAccessTokenManagement配置Redis缓存?

方案可行性及实现步骤

该方案完全可行,IdentityModel.AspNetCore框架支持自定义令牌缓存存储,通过替换默认内存缓存为Redis,可实现多App Service实例共享令牌,避免各实例重复向授权服务器请求令牌的问题。

具体实现步骤

1. 安装必要NuGet包

Install-Package StackExchange.Redis
Install-Package IdentityModel.AspNetCore
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis

2. 配置Redis缓存服务

在Program.cs中添加Redis分布式缓存配置:

builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("Redis");
    options.InstanceName = "TokenCache:";
});

3. 实现Redis令牌缓存

自定义实现IClientTokenCache接口,基于Redis存储令牌:

public class RedisClientTokenCache : IClientTokenCache
{
    private readonly IDistributedCache _distributedCache;
    private readonly ILogger<RedisClientTokenCache> _logger;

    public RedisClientTokenCache(IDistributedCache distributedCache, ILogger<RedisClientTokenCache> logger)
    {
        _distributedCache = distributedCache;
        _logger = logger;
    }

    public async Task<ClientToken> GetAsync(string clientName, CancellationToken cancellationToken = default)
    {
        var cacheKey = $"ClientToken:{clientName}";
        var tokenJson = await _distributedCache.GetStringAsync(cacheKey, cancellationToken);
        return string.IsNullOrEmpty(tokenJson) ? null : JsonSerializer.Deserialize<ClientToken>(tokenJson);
    }

    public async Task SetAsync(string clientName, ClientToken token, CancellationToken cancellationToken = default)
    {
        if (token == null) return;
        
        var cacheKey = $"ClientToken:{clientName}";
        var tokenJson = JsonSerializer.Serialize(token);
        // 提前1分钟过期,避免使用已失效的令牌
        var expiration = token.Expiration.Subtract(DateTime.UtcNow).AddMinutes(-1);
        
        await _distributedCache.SetStringAsync(
            cacheKey, 
            tokenJson, 
            new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = expiration }, 
            cancellationToken);
    }

    public async Task RemoveAsync(string clientName, CancellationToken cancellationToken = default)
    {
        var cacheKey = $"ClientToken:{clientName}";
        await _distributedCache.RemoveAsync(cacheKey, cancellationToken);
    }
}

4. 替换默认令牌缓存

修改原有服务注册代码,将默认内存缓存替换为自定义Redis缓存:

foreach (var tokenEndpointConfiguration in tokenEndpointConfigurations)
{
    services.AddAccessTokenManagement(options =>
    {
        options.Client.Clients.Add(tokenEndpointConfiguration.Name, new ClientCredentialsTokenRequest()
        {
            Address = tokenEndpointConfiguration.TokenUrl,
            ClientId = tokenEndpointConfiguration.ClientId,
            ClientSecret = tokenEndpointConfiguration.ClientSecret
        });
    })
    .AddClientAccessTokenCache<RedisClientTokenCache>(); // 替换缓存实现

    services.AddHttpClient(tokenEndpointConfiguration.Name, c =>
    {
        c.BaseAddress = new Uri(tokenEndpointConfiguration.BaseUrl);
    })
    .AddClientAccessTokenHandler(tokenClientName: tokenEndpointConfiguration.Name);
}

services.AddSingleton<HttpClientSelectorService>();
services.AddSingleton<IClientTokenCache, RedisClientTokenCache>();

注意事项

  • 确保所有App Service实例能访问同一Redis集群/实例,配置正确的连接字符串。
  • 令牌缓存过期时间需预留缓冲(如提前1分钟),避免因网络延迟等问题使用已失效令牌。
  • 建议配置Redis的高可用方案(如哨兵、集群),避免单点故障影响令牌获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 12:24:57