【发布时间】: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