【问题标题】:ASP.NET Core 3.1 Unable to unprotect the message.State running in debuggerASP.NET Core 3.1 无法取消保护在调试器中运行的 message.State
【发布时间】:2022-08-16 08:31:31
【问题描述】:

我使用默认模板从 VS 2022 创建了一个 ASP.NET Core 3.1 Web 应用程序,并选择了 Microsoft Identity 以使用 Azure AD 身份验证。向导在我的 Azure AD 租户中生成了应用注册,一切看起来都不错(回复 URL 等)

当我从调试器运行新生成的 Web 应用程序时,系统提示我输入我的 Azure AD 凭据,然后我被重定向回我的应用程序并得到以下异常:

Exception: Unable to unprotect the message.State.

Unknown location
Exception: An error was encountered while handling the remote login.

Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()

请注意,我没有添加或修改任何代码。它是 100% 由 VS2022 模板生成的。

  • 我用谷歌搜索了你的异常,我找到了this issue,我想检查你是否使用 IIS Express 来调试你的应用程序? i.stack.imgur.com/raaKb.png
  • @TinyWang 是的,我使用 IIS Express 在本地进行调试。
  • 谢谢先生的确认。而在这种情况下,如果您想弄清楚为什么使用 VS 2022 中的默认 Temple 会导致问题,我没有其他想法,但如果您只想找到一种方法将 azure ad 集成到您的 MVC 项目中以使用户登录,可以参考我的this answer,里面有代码和配置。

标签: asp.net-core azure-active-directory


【解决方案1】:
  • 此错误“例外:无法取消保护消息。状态”, 通常发生在你有多个 OIDC 中间件.如果有多个,请检查是否需要为每个 OIDC 设置唯一的回调路径。
  • 为每个 OIDC 提供者命名身份验证方案,例如oidc-demooidc-master.
  • 状态参数返回时未正​​确解密可能是因为您的 OIDC 提供商之一试图解密/取消保护另一个的消息状态。
  • 尝试添加数据保护提供商根据github 讨论。

请检查以下链接数据保护:

Configure ASP.NET Core Data Protection | Microsoft Docs

c# - Azure AD Authentication in Kubernetes Unable to unprotect the message.State - Stack Overflow

  • 确保重定向URI应该是您自己的控制器中的操作方法,如下所示:

            https://localhost:44381/test/callback 
    
  • 检查 UnProtect 方法OnMessageReceived按照link 中的讨论进行解密。

欲知更多详情,请参考以下链接:

asp.net core - Error code 500 "Unable to unprotect the message.State" when redirecting to Client in IdentityServer4 - Stack Overflow

【讨论】:

  • 该项目是通过选择从 VS 2022 创建新的 ASP.NET Core 3.1 Web 应用程序,然后在向导中选择“Microsoft 身份平台”来生成的。接下来基本上只是单击创建,然后在连接的服务对话框中配置“Microsoft 身份平台”。我没有从默认生成的代码中修改任何一行代码。我没有多个 OIDC 中间件。
【解决方案2】:

我在使用 Azure AD auth 的 vanilla ASP.NET 6 模板时遇到了同样的问题,除了在本地一切正常,但是当我将它部署到我们的 kubernetes 集群时,我收到了Unable to unprotect the message.State. 错误。

对我来说,问题是应用程序被部署到负载均衡器后面的多个实例,因此导致了问题。我遇到了this issue on GitHub,它把我指向了描述问题和解决方案的this article

解决方案 1

这篇文章建议使用一个可以被所有正在运行的实例共享的集中式数据存储来保存身份验证密钥,并使用与此类似的代码进行设置。

services.AddDataProtection()
    .SetApplicationName("MyApp")
    .SetDefaultKeyLifetime(TimeSpan.FromDays(30))
    .PersistKeysToAzureBlobStorage(new Uri("https://mystore.blob.core.windows.net/keyrings/master.xml"), new DefaultAzureCredential())
    .ProtectKeysWithAzureKeyVault(new Uri("https://myvault.vault.azure.net/keys/MasterEncryptionKey"), new DefaultAzureCredential());

解决方案 2

我的 Web 应用程序没有使用数据库,我不想仅仅为了身份验证而引入一个数据库,因此我将我们的入口配置为使用 cookie 持久性。这意味着当发出请求时,响应包含客户端将存储并包含在未来请求中的 cookie。 cookie 告诉入口将请求定向到哪个实例,以确保来自特定客户端的请求始终最终到达同一个实例。

这在所有场景中可能并不理想,因为它可能会阻止负载均衡器在所有实例中执行请求的平均分配。不过,在我的场景中,这种权衡很好,因为它不是高容量服务,这就是我最终使用的解决方案。

解决方案 3

最后一个选项是只托管您的服务的单个实例,在这种情况下,所有身份验证回调都将命中该单个服务。但这并不理想,因为这意味着您无法扩展您的 Web 应用程序以实现高可用性。


这与原始发布者在调试时在其本地主机上出现此错误的问题有何关系,我不确定。也许他们有不止一次的实例在他们的本地机器上运行,或者在他们的本地主机上运行的反向代理或拦截器(如 Fiddler)导致了问题?无论哪种方式,我想我会为其他在搜索错误消息时偶然发现这个问题的人分享我的解决方案。

【讨论】:

    猜你喜欢
    • 2017-05-13
    • 2021-04-14
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2021-01-03
    • 2020-07-06
    • 2020-10-09
    • 1970-01-01
    相关资源
    最近更新 更多