我有一個使用WIF保護的wcf服務。我執行客戶(網站)上令牌緩存,在特拉維斯斯賓塞的博客描述如下:Wif安全的WCF服務,緩存令牌 - 異步wcf方法丟失身份
http://travisspencer.com/blog/2009/03/caching-tokens-to-avoid-calls.html
的網站使用模擬(冒充我),和WCF端點的STS配置爲使用Windows身份驗證。
當使用直接調用(即非異步調用)調用WCF服務時,令牌緩存工作正常 - ClientCredentials行爲已刪除,並添加了我的自定義CacheClientCredentials行爲,並且令牌在第一次調用時被緩存,並在隨後的通話。
但是我有一個場景,其中提供了一個回調,在wcf服務上調用異步方法。在正常情況下(非異步),會多次調用CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider方法,並且每次調用時線程運行的標識都是正確的。隨後對STS的調用使用正確的憑證,用戶通過身份驗證並返回令牌。當調用異步方法時,會發生對CacheClientCredentialsSecurityTokenManager.CreateSecurityTokenProvider的多次調用,但只有第一次調用具有正確的標識。隨後的呼叫具有「NT AUTHORITY \ NETWORK SERVICE」作爲身份。因此,對STS的調用具有錯誤的憑據,並且身份驗證失敗。 (STS日誌顯示一條消息,指示「無法驗證」
我一直試圖在開始/結束異步方法周圍添加顯式模仿,但這並不是一直工作。在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]