托管在Azure的Dot net MVC5应用反复重定向至登录页,重启后才可恢复
故障根因定位
这个低负载正常、高并发突发全用户登录循环、重启恢复的典型表现,核心是用户身份状态持久化失效,结合你给出的代码,常见触发点如下:
- 会话存储使用默认InProc模式:你当前用
SessionTokenStore将会话绑定到当前Web实例的内存中,Azure Web App高并发场景下会触发以下问题:- 应用池因内存占用/定时回收规则自动重启,内存内所有会话数据全部清空
- 多实例负载均衡时用户请求漂移到其他实例,对应实例内存无该用户的会话缓存
- 高并发下会话存储溢出,旧会话被主动清理
ConfidentialClientApplication未使用单例模式:你每次授权码流都新建实例,MSAL的令牌缓存默认绑定实例,高并发下大量重复实例会导致内存泄漏、令牌缓存冲突,最终触发应用池强制回收,全用户状态丢失- 下游API调用无容错机制:
AuthorizeUserByEmailID调用后端API时如果高并发下出现超时、限流、报错,你当前逻辑直接拦截响应跳转,未做重试或降级,当API可用性波动时会触发大面积重定向
修复方案
1. 替换会话存储为分布式缓存
将默认的内存会话替换为Azure Redis缓存等分布式存储,保证多实例、应用池重启后会话数据不丢失:
首先安装NuGet包:Microsoft.Web.RedisSessionStateProvider,然后在web.config中配置:
<sessionState mode="Custom" customProvider="RedisSessionStateProvider"> <providers> <add name="RedisSessionStateProvider" type="Microsoft.Web.Redis.RedisSessionStateProvider" connectionString="你的Redis连接字符串" throwOnError="false" /> </providers> </sessionState>
2. 将ConfidentialClientApplication注册为单例
在Startup中全局初始化一次MSAL客户端,避免重复创建实例:
// 全局静态单例声明 public static IConfidentialClientApplication MsalClient { get; private set; } // 在Startup.Configuration方法中初始化 var authority = string.Format("https://login.microsoftonline.com/{0}/v2.0", ConfigurationManager.AppSettings["TenantID"]); MsalClient = ConfidentialClientApplicationBuilder.Create(appId) .WithRedirectUri(redirectUri) .WithClientSecret(appSecret) .WithAuthority(authority) .Build();
后续授权逻辑直接复用该静态单例即可,不要每次请求新建。
3. 给下游API调用增加容错逻辑
给AuthorizeUserByEmailID增加重试、超时控制,API异常时优先使用本地已有的身份信息兜底,不要直接跳转登录:
// 示例:增加Polly重试策略 var retryPolicy = Policy.Handle<HttpRequestException>() .WaitAndRetryAsync(3, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))); authOutput = await retryPolicy.ExecuteAsync(() => methodHelper.AuthorizeUserByEmailID(cachedUser.Email));
4. 验证身份Cookie配置
确认Startup.Auth.cs中Cookie配置适配Azure Web App负载均衡场景,开启Cookie加密适配多实例:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), CookieSecure = CookieSecureOption.Always, CookieSameSite = SameSiteMode.Lax, SlidingExpiration = true, ExpireTimeSpan = TimeSpan.FromHours(8) });
同时要确保Azure Web App的机器密钥配置为全局统一,不要用自动生成的实例级密钥,避免跨实例Cookie解密失败。
内容的提问来源于stack exchange,提问作者saikat mukherjee
相关产品推荐
相关产品推荐

