2011-04-28 80 views
3

我有一個使用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] 

回答

3

我沒有蜜蜂n在嘗試調用異步方法之前明確調用代理上的.Open(),結果.Open()看起來發生在客戶端代理內部,另一個線程上 - 因此存在身份問題。我發現,如果我叫:

If _proxy.State <> CommunicationState.Opened Then 
    _proxy.Open() 
End If 

_proxy.Begin[asyncMethod]() 

緩存憑據設置和令牌緩存檢查發生同步,因此使用正確的身份,並作爲預期。