Azure active directory 如何在负载平衡环境中使用Azure AD配置Blazor服务器应用程序?

Azure active directory 如何在负载平衡环境中使用Azure AD配置Blazor服务器应用程序?,azure-active-directory,blazor,blazor-server-side,blazor-webassembly,asp.net-blazor,Azure Active Directory,Blazor,Blazor Server Side,Blazor Webassembly,Asp.net Blazor,我有一个内部网Blazor服务器应用程序,它是使用Visual Studio模板创建的,带有工作或学校帐户身份验证选项。当我在本地机器上运行时,以及当应用程序发布到我们的开发环境时,一切都运行得很好。然而,一旦我将应用程序移动到我们的登台环境中,应用程序有时会在Azure中对用户进行身份验证后崩溃 在对问题进行故障排除之后,我认为问题在于我们的本地登台环境是负载平衡的(模拟生产)。我们的开发环境不是负载平衡的。我认为发生的事情是,一旦在Azure中进行身份验证并重定向回应用程序,由于负载平衡器的

我有一个内部网Blazor服务器应用程序,它是使用Visual Studio模板创建的,带有工作或学校帐户身份验证选项。当我在本地机器上运行时,以及当应用程序发布到我们的开发环境时,一切都运行得很好。然而,一旦我将应用程序移动到我们的登台环境中,应用程序有时会在Azure中对用户进行身份验证后崩溃

在对问题进行故障排除之后,我认为问题在于我们的本地登台环境是负载平衡的(模拟生产)。我们的开发环境不是负载平衡的。我认为发生的事情是,一旦在Azure中进行身份验证并重定向回应用程序,由于负载平衡器的原因,用户并不总是在同一台服务器上登录。这会断开Signal-R电路并导致应用程序崩溃。这也解释了为什么误差是随机的;每10次登录尝试中可能有2次发生。为了测试这一点,我从应用程序中删除了Azure AD身份验证,并允许匿名访问每个页面。车祸停止了

我的问题是,是否有人知道有什么解决方法可以让Blazor Server with Azure AD authentication与本地负载平衡器一起工作。我搜索了整个网络,找到的唯一解决办法是使用Azure Signal R服务的粘性会话。我们还没有在云上托管应用程序。如果我想在我的环境中使用Blazor进行身份验证,切换到Blazor Webassembly是唯一的选择吗?有人建议将应用程序切换为使用我们的本地ADFS服务器。然而,这不会遇到同样的问题吗

以下是startup.cs ConfigureServices方法中用于在应用程序中设置Azure身份验证的代码,以供参考:

services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
            .AddAzureAD(options => Configuration.Bind("AzureAd", options));


        services.AddControllersWithViews(options =>
        {
            var policy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
            

            options.Filters.Add(new AuthorizeFilter(policy));
        });

我找到了解决这个问题的方法,并将其发布在这里,以防其他人也面临类似的问题

原来问题不是signar或Blazor服务器特有的任何东西。在负载平衡环境中启用开发者异常页面后,我看到错误是“无法取消对message.State的保护”。在Azure AD对用户进行身份验证之前,应用程序状态由中间件进行加密。当Azure AD发回时,它包括加密状态,然后由中间件在客户端解密

解密所需的密钥存储在web服务器上。在负载平衡环境中,如果您的服务器与启动服务器不同,那么中间件将尝试使用错误的密钥解密状态。这当然会导致错误

要解决此问题,您必须将密钥存储在中心位置,如文件共享,而不是服务器本身。实现修复实际上很简单。在startup.cs中的ConfigureServices中包括以下行:

services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"));
如果愿意,还可以选择在Azure上存储密钥

Kevin Dockx的这篇文章最终给了我答案: