【问题标题】:Wif secured WCF service, caching tokens - async wcf method loses identityWifi 安全 WCF 服务,缓存令牌 - 异步 wcf 方法丢失身份
【发布时间】:2011-08-14 07:46:40
【问题描述】:

我有一个使用 WIF 保护的 wcf 服务。我正在客户端(一个网站)上实现令牌缓存,如 Travis Spencer 的博客所述:

http://travisspencer.com/blog/2009/03/caching-tokens-to-avoid-calls.html

网站正在使用模拟(模拟我),并且 STS wcf 端点配置为使用 Windows 身份验证。

当使用直接调用(即非异步调用)调用 WCF 服务时,令牌缓存工作正常 - 删除 ClientCredentials 行为并添加我的自定义 CacheClientCredentials 行为,并在第一次调用时缓存令牌并在后续调用中重用称呼。

但是,我有一个场景,其中在 wcf 服务上调用了一个异步方法,并提供了一个回调。在正常情况下(非异步),多次调用 CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider 方法,并且在每次调用时,线程运行的身份都是正确的。对 STS 的后续调用使用正确的凭据,用户通过身份验证并返回令牌。调用 async 方法时,会发生对 CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider 的多次调用,但只有第一次调用具有正确的标识。随后的调用以“NT AUTHORITY\NETWORK SERVICE”作为标识。因此,对 STS 的调用具有错误的凭据,并且身份验证失败。 (STS 日志显示一条​​消息,指示“无法通过身份验证”。

我一直在尝试围绕 Begin/End 异步方法添加显式模拟,但这并不是一直有效。然后我将以下值添加到 web.config:

    <legacyImpersonationPolicy enabled="false" />
    <alwaysFlowImpersonationPolicy enabled="true" />

这也并不总是有效(尽管有时有效)。这里不寻常的是,业务逻辑涉及 3 次尝试调用异步方法(如果调用失败)。我发现通常前两个失败,第三个成功 - 即 CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider 通常在前两次以错误的身份运行,第三次以正确的身份运行 - 但这似乎也有点随机。当 CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider 使用正确的标识成功时,WCF 调用成功。但是令牌不会添加到缓存中(不执行令牌缓存代码) 对非异步方法的后续调用然后构造一个新的缓存然后获取令牌,将其添加到缓存中。

调用使用 WIF 保护的异步 WCF 方法以确保跨调用缓存 WIF 令牌的正确方法是什么?

是否需要特殊的身份配置来确保在所有这些进程中使用相同的身份? (所有领域都在使用模仿)

更新:

我不确定它是否增加了很多,但我发现当代码不起作用时,以下是 CacheClientCredentialsSecurityTokenManager 中的堆栈跟踪:

Unflagged   >   5732    18  Worker Thread   <No Name>   CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider  Normal
                        MySecurity.dll!CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(System.IdentityModel.Selectors.SecurityTokenRequirement tokenRequirement) Line 18  
                        System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.AddSupportingTokenProviders(System.ServiceModel.Security.Tokens.SupportingTokenParameters supportingTokenParameters, bool isOptional, System.Collections.Generic.IList<System.ServiceModel.Security.SupportingTokenProviderSpecification> providerSpecList) + 0xca bytes   
                        System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.OnOpen(System.TimeSpan timeout) + 0xa7 bytes   
                        System.ServiceModel.dll!System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(System.TimeSpan timeout) + 0x45 bytes  
                        System.ServiceModel.dll!System.ServiceModel.Security.OperationWithTimeoutAsyncResult.OnScheduled(object state) + 0x82 bytes  
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() + 0x46 bytes    
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.OnSecurityContextCallback(object o) + 0x28 bytes  
                        mscorlib.dll!System.Security.SecurityContext.Run(System.Security.SecurityContext securityContext, System.Threading.ContextCallback callback, object state) + 0x55 bytes  
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() + 0x4d bytes     
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() + 0x180 bytes   
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(object state) + 0x7a bytes  
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0xf bytes     
                        SMDiagnostics.dll!System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x3d bytes    
                        mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x54 bytes     
                        [Appdomain Transition]  

当它起作用时,它有点不同(注意额外的 mscorlib 条目和中间的转换):

Unflagged   >   5408    12  Worker Thread   <No Name>   CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider  Normal
                        MySecurity.dll!CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider(System.IdentityModel.Selectors.SecurityTokenRequirement tokenRequirement) Line 18  
                        System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.AddSupportingTokenProviders(System.ServiceModel.Security.Tokens.SupportingTokenParameters supportingTokenParameters, bool isOptional, System.Collections.Generic.IList<System.ServiceModel.Security.SupportingTokenProviderSpecification> providerSpecList) + 0xca bytes   
                        System.ServiceModel.dll!System.ServiceModel.Security.SecurityProtocol.OnOpen(System.TimeSpan timeout) + 0xa7 bytes   
                        System.ServiceModel.dll!System.ServiceModel.Security.SymmetricSecurityProtocol.OnOpen(System.TimeSpan timeout) + 0x45 bytes  
                        System.ServiceModel.dll!System.ServiceModel.Security.OperationWithTimeoutAsyncResult.OnScheduled(object state) + 0x82 bytes  
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke2() + 0x46 bytes    
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.OnSecurityContextCallback(object o) + 0x28 bytes  
                        ***mscorlib.dll!System.Security.SecurityContext.runTryCode(object userData) + 0x6e bytes     
                        [Native to Managed Transition]   
                        [Managed to Native Transition]   
                        ***mscorlib.dll!System.Security.SecurityContext.RunInternal(System.Security.SecurityContext securityContext, System.Threading.ContextCallback callBack, object state) + 0xc2 bytes   
                        ***mscorlib.dll!System.Security.SecurityContext.Run(System.Security.SecurityContext securityContext, System.Threading.ContextCallback callback, object state) + 0xca bytes   
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.WorkItem.Invoke() + 0x4d bytes     
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ProcessCallbacks() + 0x180 bytes   
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.CompletionCallback(object state) + 0x7a bytes  
                        System.ServiceModel.dll!System.ServiceModel.Channels.IOThreadScheduler.CriticalHelper.ScheduledOverlapped.IOCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) + 0xf bytes     
                        SMDiagnostics.dll!System.ServiceModel.Diagnostics.Utility.IOCompletionThunk.UnhandledExceptionFrame(uint error, uint bytesRead, System.Threading.NativeOverlapped* nativeOverlapped) + 0x3d bytes    
                        mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) + 0x54 bytes     
                        [Appdomain Transition]   

【问题讨论】:

    标签: wcf caching asynchronous token wif


    【解决方案1】:

    在尝试调用异步方法之前,我没有在代理上显式调用.Open(),因此.Open() 似乎发生在客户端代理内部的另一个线程上——因此存在身份问题。我发现如果我打电话:

    If _proxy.State <> CommunicationState.Opened Then
         _proxy.Open()
    End If
    
    _proxy.Begin[asyncMethod]()
    

    缓存凭据设置和令牌缓存检查同步发生,因此使用正确的身份,并按预期运行。

    【讨论】:

      猜你喜欢
      • 2012-07-06
      • 1970-01-01
      • 1970-01-01
      • 2013-03-12
      • 1970-01-01
      • 2010-09-28
      • 1970-01-01
      相关资源
      最近更新 更多