Asp.Net Core MVC集成Azure AD认证时出现Correlation failed错误求助
我之前在维护Web场部署的Asp.Net Core应用时,也碰到过一模一样的Azure AD认证关联失败问题——单台服务器直接访问完全正常,一经过负载均衡就抛Correlation failed异常。结合你的场景,这个问题基本都是服务器间状态不共享或者负载均衡的配置没跟上导致的,给你几个实测有效的解决办法:
1. 统一所有服务器的数据保护密钥
Asp.Net Core靠数据保护系统加密认证相关的Cookie,Web场里如果每台服务器的密钥不一样,其他服务器就没法解密之前生成的关联Cookie,直接就会触发关联失败。
你可以在Startup.cs里配置一个共享的密钥存储位置,比如用Azure Blob存储(云环境最方便):
public void ConfigureServices(IServiceCollection services) { // 先保留你原有配置,再添加这段数据保护配置 services.AddDataProtection() .PersistKeysToAzureBlobStorage(new Uri("https://你的存储账户.blob.core.windows.net/密钥存储容器/keys.xml")) .SetApplicationName("你的应用名称"); // 所有服务器必须用同一个应用名称 }
如果是本地文件共享部署,也可以用PersistKeysToFileSystem(new DirectoryInfo(@"\\共享存储路径\keys")),注意要保证所有服务器都能读写这个共享目录。
2. 开启负载均衡器的会话亲和性(粘性会话)
如果负载均衡器没开粘性会话,你的认证请求可能先落到Server A,回调的时候却跳去了Server B——而Server B根本没保存之前的认证关联状态,自然就失败了。
你需要在负载均衡器里开启源IP亲和性或者Cookie亲和性,让同一个用户的认证请求全程落到同一台服务器上。不过这个算是临时缓解方案,最好还是配合上面的密钥共享一起做,不然粘性会话会影响负载均衡的分流效果。
3. 核对Azure AD应用的回调URL配置
务必确保Azure AD应用注册里的回调URL是负载均衡器的公共地址,而不是单台服务器的地址。比如应该填https://你的负载均衡域名/signin-oidc,而不是某台服务器的https://server1.example.com/signin-oidc。
同时检查Startup.cs里的Azure AD认证配置,确保CallbackPath和注册的完全一致:
services.AddAuthentication(AzureADDefaults.AuthenticationScheme) .AddAzureAD(options => { Configuration.Bind("AzureAd", options); // 手动指定回调路径,确保和Azure AD注册的一致 options.CallbackPath = "/signin-oidc"; });
4. 配置负载均衡器的HTTPS头转发
如果负载均衡器做了SSL终止(也就是负载均衡器对外处理HTTPS,后端服务器用HTTP),一定要让负载均衡器转发X-Forwarded-Proto这类头信息——不然Asp.Net Core会误以为请求是HTTP的,导致认证回调时的URL协议不匹配,触发关联失败。
在Startup.cs的Configure方法里,把转发头的中间件放在认证中间件之前:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // 添加这段转发头配置 app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedFor }); // 原有配置 app.UseAuthentication(); app.UseMvc(); }
另外别忘了在负载均衡器那边开启头转发(比如Azure应用网关要在“后端HTTP设置”里勾选“启用X-Forwarded-For”)。
5. 调整Cookie的安全配置
Web场环境下,要确保认证Cookie的SameSite和Secure属性配置正确:
public void ConfigureServices(IServiceCollection services) { services.Configure<CookiePolicyOptions>(options => { options.MinimumSameSitePolicy = SameSiteMode.Lax; options.Secure = CookieSecurePolicy.Always; // 只在HTTPS请求中发送Cookie }); }
然后在Configure方法里添加app.UseCookiePolicy();,而且要放在UseAuthentication()之前。
优先搞定数据保护密钥共享的问题,这是Web场下状态一致性的核心,再配合负载均衡的头转发和会话配置,基本就能解决这个Correlation failed的异常了。
内容的提问来源于stack exchange,提问作者alerancur

