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
相关产品推荐
相关产品推荐

