.NET 8/C#12中用户分配托管身份认证Azure Redis缓存的自动续期问题
用用户分配托管身份自动认证Azure Redis Cache(.NET 8/C# 12)
核心思路
要实现自动认证,需完成两个关键环节:
- 通过Azure Identity库获取带过期时间的Entra令牌
- 在令牌过期前主动刷新并重新执行Redis AUTH命令
1. 获取Entra令牌及过期时间
使用Azure.Identity库的ManagedIdentityCredential(针对用户分配托管身份)获取令牌,令牌对象的ExpiresOn属性直接提供过期时间。需要指定托管身份的Client ID,以及Redis专属的令牌范围https://redis.azure.com/.default。
2. 自动刷新Redis AUTH的实现
用后台定时任务(如Timer)定期检查令牌状态,在过期前10分钟左右刷新令牌,然后调用Redis的AUTH命令更新认证信息。主动刷新比依赖连接失败事件兜底更可靠。
完整代码示例
先安装必要的NuGet包:
Install-Package Azure.Identity Install-Package StackExchange.Redis
using Azure.Identity; using StackExchange.Redis; using System.Timers; namespace RedisManagedIdentityAuth { public class RedisAuthManager { private readonly ConnectionMultiplexer _redisMultiplexer; private readonly string _managedIdentityObjectId; // 托管身份的对象ID private readonly string _managedIdentityClientId; // 用户分配托管身份的Client ID private readonly Timer _refreshTimer; private AccessToken _currentToken; public RedisAuthManager(string redisConnectionString, string managedIdentityObjectId, string managedIdentityClientId) { _managedIdentityObjectId = managedIdentityObjectId; _managedIdentityClientId = managedIdentityClientId; // 初始化Redis连接(仅基础连接,不含认证信息) _redisMultiplexer = ConnectionMultiplexer.Connect(redisConnectionString); // 每5分钟检查一次令牌状态 _refreshTimer = new Timer(5 * 60 * 1000); _refreshTimer.Elapsed += RefreshTokenAndAuth; _refreshTimer.AutoReset = true; // 首次启动时完成认证 RefreshTokenAndAuth(null, null); } private async void RefreshTokenAndAuth(object sender, ElapsedEventArgs e) { try { // 令牌剩余有效期大于10分钟则跳过刷新 if (_currentToken.ExpiresOn > DateTimeOffset.UtcNow.AddMinutes(10)) { return; } // 获取新的Entra令牌 var credential = new ManagedIdentityCredential(_managedIdentityClientId); _currentToken = await credential.GetTokenAsync(new Azure.Core.TokenRequestContext( new[] { "https://redis.azure.com/.default" })); // 执行Redis AUTH命令完成认证 var server = _redisMultiplexer.GetServer(_redisMultiplexer.GetEndPoints().First()); server.Execute("AUTH", _managedIdentityObjectId, _currentToken.Token); Console.WriteLine($"Redis认证刷新成功,新令牌过期时间:{_currentToken.ExpiresOn:yyyy-MM-dd HH:mm:ss}"); } catch (Exception ex) { Console.WriteLine($"刷新Redis认证失败:{ex.Message}"); // 可添加重试逻辑,比如间隔30秒后重试 } } // 暴露Redis数据库实例供业务代码调用 public IDatabase GetDatabase(int db = 0) { return _redisMultiplexer.GetDatabase(db); } } // 使用示例 public class Program { public static async Task Main(string[] args) { var redisConnectionString = "your-redis-cache.redis.cache.windows.net:6380,ssl=True"; var managedIdentityObjectId = "your-managed-identity-object-id"; var managedIdentityClientId = "your-user-assigned-managed-identity-client-id"; var authManager = new RedisAuthManager(redisConnectionString, managedIdentityObjectId, managedIdentityClientId); var db = authManager.GetDatabase(); // 测试Redis读写 await db.StringSetAsync("test-key", "test-value", TimeSpan.FromMinutes(30)); var value = await db.StringGetAsync("test-key"); Console.WriteLine($"Redis取值:{value}"); // 保持程序运行 Console.ReadLine(); } } }
关键注意事项
- 权限配置:确保用户分配托管身份被授予Azure Redis Cache的
Redis Cache Contributor角色,或包含Microsoft.Cache/redisCache/keys/*权限的自定义角色。 - 令牌范围:必须使用
https://redis.azure.com/.default作为令牌请求范围,否则获取的令牌无法通过Redis认证。 - 刷新时机:设置在令牌过期前10-15分钟刷新,避免网络延迟等问题导致令牌过期后才触发刷新。
- 错误处理:添加重试逻辑处理令牌获取失败或Redis认证失败的场景,提升系统可用性。
内容的提问来源于stack exchange,提问作者santosh kumar patro
相关产品推荐
相关产品推荐

