Azure 上的联合身份验证

Posted

技术标签:

【中文标题】Azure 上的联合身份验证【英文标题】:Federated Authentication on Azure 【发布时间】:2012-12-16 16:43:49 【问题描述】:

我正在使用 WIF (.net 4.5) 和 Azure Active Directory 进行身份验证。该网站将位于 Azure 上。

一切都按预期在本地工作,但是当我把它放到 azure 上时,我得到了错误:

数据保护操作不成功。这可能是由于没有为当前线程的用户上下文加载用户配置文件造成的,这可能是线程模拟时的情况。

我知道这是因为应用程序无法使用 DAPI,所以我需要切换到使用 MAC 保护我的应用程序。

我在本地将它添加到我的 webconfig 中:-

 <securityTokenHandlers>
    <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
    <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  </securityTokenHandlers>

按照documentation 中的建议,我添加了一个静态机器密钥,但我找不到任何关于密钥长度的建议 - 所以我假设为 256。

然而,这个配置只是给出了这个错误:

[CryptographicException:加密操作期间发生错误。] System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.HomogenizeErrors(Func`2 func, Byte[] 输入) +115 System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.Unprotect(Byte[] protectedData) +59 System.Web.Security.MachineKey.Unprotect(ICryptoServiceProvider cryptoServiceProvider, Byte[] protectedData, String[] 目的) +62 System.Web.Security.MachineKey.Unprotect(Byte[] protectedData, String[] 用途) +122 System.IdentityModel.Services.MachineKeyTransform.Decode(字节 [] 编码)+161 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +123 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver) +575 System.IdentityModel.Tokens.SessionSecurityTokenHandler.ReadToken(Byte[] token, SecurityTokenResolver tokenResolver) +76 System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +833 System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(对象发送者,EventArgs eventArgs)+210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

如果我没有指定格式正确的密钥,我删除了 machinekey 部分,但错误并没有消失。

WIF 是一场多么激烈的战斗!

【问题讨论】:

为了解决我的问题,我将其添加到 web.config 并使用此站点生成了一个机器密钥aspnetresources.com/tools/machineKey 【参考方案1】:

如果你没有在配置中指定 machineKey,Azure 会添加一个。但是,如果您创建应用程序的新版本并使用 VIP 切换将其部署到 Azure,Azure 会为暂存中的部署生成一个新的机器密钥(假设您的第一次部署是到生产)。 (VIP 切换是部署新版本然后在 Production 和 Staging 之间切换虚拟 IP 地址的好机制。

所以基本上一种解决方案是让 Azure 生成密钥,但在 VIP 切换后你又遇到了问题。为避免这种情况,您可以在 Application_Error 处理程序中捕获 Global.asax 中的 CryptographicException,如下所示:

// Be sure to reference System.IdentityModel.Services
// and include using System.IdentityModel.Services; 
// at the start of your class
protected void Application_Error(object sender, EventArgs e)

    var error = Server.GetLastError();
    var cryptoEx = error as CryptographicException;
    if (cryptoEx != null)
    
        FederatedAuthentication.WSFederationAuthenticationModule.SignOut();
        Server.ClearError();
    

SignOut() 方法导致 cookie 被删除。

编辑:如@anjdreas 所述,更新了有关生成 machineKey 的信息。

另一种解决方案是生成machineKey,你可以使用IIS Manager来做,详情见Easiest way to generate MachineKey。如果您将相同的密钥放入 Azure Web 角色中的所有 Web 应用程序,Azure 部署过程将不会替换它。

【讨论】:

如果您不想使用第三方站点,您也可以使用 IIS 管理器为您生成密钥。 blogs.msdn.com/b/amb/archive/2012/07/31/… aspnetresources.com 现在似乎是一个托管域。你应该用 anjdreas 的链接重写最后一段 FederatedAuthentication.WSFederationAuthenticationModule 中的 FederatedAuthentication 表示“FederatedAuthentication.WSFederationAuthenticationModule”中的名称在当前上下文中不存在,并且找不到我需要添加的内容。使用 .net 4.6 @JQuery 程序集 System.IdentityModel.Services,命名空间:System.IdentityModel.Services。见msdn 谢谢,我可以使用 System.IdentityModel 添加到 global.asx,但是当我尝试添加服务时,我得到名称空间“System.IdentityModel”中不存在类型或名称空间名称“Services”(您是否缺少程序集参考?)使用指令是不必要的。【参考方案2】:

机器密钥不应该在那里:Windows Azure 会为您生成一个,并确保它在您角色中的每个实例上都是相同的。

关于您看到的错误:您可以尝试清除 cookie 吗?

【讨论】:

虚幻的,这样就搞定了!谢谢!! 原因是你可能先用常规会话管理器尝试过 -> 它留下了一个无法解密的 cookie,因为你基本上改变了切换到机器密钥的机制:-) 是的,现在我想起来了!感谢您的帮助。 他们应该真正清除“坏”cookie,而不是仅仅抱怨有问题;)【参考方案3】:

在这种情况下,只需清除 cookie 就解决了我的整个问题。

【讨论】:

清除 cookie 也对我们有用,但此解决方案并非最佳解决方案,因为用户仍会看到错误并需要有关如何清除 cookie 的说明。不过,这是一个解决方案,非常感谢。【参考方案4】:

如果您使用的是表单身份验证。您可以在捕获异常时退出并允许您的用户登录并创建有效的 cookie

catch (CryptographicException cex)

    FormsAuthentication.SignOut();

【讨论】:

我们在解决方案中遇到问题,自动将用户注销。使用这种技术删除 cookie 并不能解决问题,并且当 cookie 被清除时,用户会反复退出。我们尝试在应用程序的 web.config 文件中显式设置机器密钥,如下所示: /system.web> 我们使用 IIS7 生成了加密密钥。我们仍然收到错误消息。【参考方案5】:

要求所有用户清除所有 cookie 对我来说并不是一个真正的选择。在this site 以及“Programming Windows Identity Federation”一书中,我找到了一个更好的解决方案(无论如何,对我来说)。如果您已经将 SSL 证书上传到 Azure,则可以使用该证书来加密所有 Azure 实例上的 cookie,您无需担心新的机器密钥、IIS 用户配置文件等。

【讨论】:

以上是关于Azure 上的联合身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Azure SQL Active Directory集成身份验证,联合域

移动设备上的 Azure App Service 身份验证问题

如果启用了身份验证,Azure 上的查询/标头太大

在本地和 Azure 上使用 Active Directory 进行身份验证

如何对 GCP Cloud Run 上的联合 GraphQL 服务进行身份验证?

无法对 Azure 上的 API 管理执行资源所有者密码 OAuth2 身份验证