27

我正在使用 WIF (.net 4.5) 和 Azure Active Directory 进行身份验证。该网站将位于 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>

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

但是,此配置仅给出此错误:

[CryptographicException: 加密操作期间发生错误。] System.Web.Security.Cryptography.HomogenizingCryptoServiceWrapper.HomogenizeErrors(Func`2 func, Byte[] input) +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(Byte[] 编码) +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(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication。 ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69SecurityTokenResolver tokenResolver) +76 System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +833 System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69SecurityTokenResolver tokenResolver) +76 System.IdentityModel.Services.SessionAuthenticationModule.ReadSessionTokenFromCookie(Byte[] sessionCookie) +833 System.IdentityModel.Services.SessionAuthenticationModule.TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication。 ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69TryReadSessionTokenFromCookie(SessionSecurityToken& sessionToken) +186 System.IdentityModel.Services.SessionAuthenticationModule.OnAuthenticateRequest(Object sender, EventArgs eventArgs) +210 System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136 System.Web.HttpApplication。 ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

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

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

4

5 回答 5

48

如果你没有在配置中指定 machineKey,Azure 会添加一个。但是,如果您创建应用程序的新版本并使用 VIP 切换将其部署到 Azure,Azure 会为暂存中的部署生成一个新的机器密钥(假设您的第一次部署是到生产环境)。(VIP 切换是部署新版本然后在生产和暂存之间切换虚拟 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 来完成,详细信息请参见生成 MachineKey的最简单方法。如果您将相同的密钥放入 Azure Web 角色中的所有 Web 应用程序,Azure 部署过程将不会替换它。

于 2013-04-23T12:21:45.633 回答
4

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

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

于 2013-01-02T12:29:52.000 回答
2

在这种情况下,简单地清除 cookie 为我解决了整个问题。

于 2014-08-02T16:12:29.727 回答
0

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

catch (CryptographicException cex)
{
    FormsAuthentication.SignOut();
}
于 2014-10-05T16:58:54.243 回答
-2

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

于 2015-03-19T01:22:56.147 回答