401 客戶端“協商”,伺服器“協商,NTLM”在呼叫 WCF 伺服器到伺服器時
好的,我已經閱讀了我可以找到的每個執行緒和問題,但令人驚訝的是還沒有找到解決方案。我試圖在我的 IIS 託管 WCF 服務 (.NET 4.0) 上要求 Windows 身份驗證,到目前為止,該服務一直是可選的。我在伺服器上有一個啟用 Windows 身份驗證的端點已經有一段時間了,有幾個遠端應用程序成功使用了它。我現在正嘗試將我們的 Web 應用程序和其他使用 WCF 服務的伺服器應用程序切換到此安全端點,方法是為它們提供與工作遠端客戶端完全相同的客戶端配置,但伺服器應用程序正在接收帶有消息的 401:
The HTTP request is unauthorized with client authentication scheme 'Negotiate'. The authentication header received from the server was 'Negotiate,NTLM'.]我為 WCF 託管站點啟用了匿名和 Windows 身份驗證。我開始使用的 Web 應用程序託管在與 WCF 服務不同的伺服器上,並且在 ASP.NET 2.0 和 Windows Server 2008 R2 Enterprise 上執行。我已經使用 allowNtlm 創建了一個客戶端行為,並將 NetworkSecurity: LAN Manager 身份驗證級別設置為 Send LM & NTLM… 在客戶端。在託管端,它設置為僅發送 NTLMv2 響應…我不知道這是否會影響伺服器/服務處理身份驗證的方式。我還嘗試在客戶端上將 allowedImpersonationLevel 設置為 Impersonation ,謝天謝地,這不起作用(因為不需要模擬)。對於在與 Web 應用程序相同的伺服器上執行的 Windows 服務和控制台應用程序,我們似乎得到了相同的結果。
這是我的伺服器配置:
<binding name="WindowsSecuredBinding"> <security mode="Transport"> <transport clientCredentialType="Windows" /> </security> </binding> ... <service behaviorConfiguration="OMWebServices.QueueServiceBehavior" name="OMWebServices.QueueService"> <endpoint address="" binding="basicHttpBinding" name="QueueEndpoint" bindingName="" contract="OMWebServices.IQueueService" /> <endpoint binding="basicHttpBinding" bindingConfiguration="WindowsSecuredBinding" name="QueueSecuredEndpoint" contract="OMWebServices.IQueueService" /> <endpoint address="mex" binding="mexHttpBinding" name="QueueMetadataEndpoint" contract="IMetadataExchange" /> </service> ... <behavior name="OMWebServices.QueueServiceBehavior"> <serviceMetadata httpGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior>這是客戶端配置:
<endpoint address="https://.../QueueService.svc" binding="basicHttpBinding" bindingConfiguration="QueueSecuredEndpoint" behaviorConfiguration="OMServiceBehavior" contract="OMQueueService.IQueueService" name="QueueSecuredEndpoint" /> <binding name="QueueSecuredEndpoint" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true"> <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <security mode="Transport"> <transport clientCredentialType="Windows" proxyCredentialType="None" realm="" /> <message clientCredentialType="UserName" algorithmSuite="Default" /> </security> </binding> .... <!-- The behavior I tried that didn't make a difference --> <behavior name="OMServiceBehavior"> <clientCredentials> <windows allowedImpersonationLevel="Impersonation" allowNtlm="True"/> </clientCredentials> </behavior>我的第一個問題是,這條錯誤消息真正告訴我的是什麼?它說客戶端方案是協商,伺服器響應協商,NTLM。如果伺服器提供 Negotiate 並且客戶端正在使用 Negotiate,那麼問題是什麼?
第二個問題是,顯然,出了什麼問題,我該如何讓它發揮作用?
編輯
好吧,這很愚蠢。問題似乎是沒有傳遞憑據。早在網站開發時,我就開始編寫程式碼以在程式碼中顯式設置憑據,但在此過程中,發現它已經在沒有顯式設置的情況下工作。所以該程式碼仍然被註釋掉。這是在 IIS 6 上執行的。現在在 IIS 7 上執行,它似乎只有在我在程式碼中明確設置憑據時才有效。我可以使用 w3wp 程序的帳戶自動獲取它嗎?
為了回答第一個問題,錯誤消息告訴我它到底在說什麼;我沒有被授權。告訴我客戶端身份驗證方案和伺服器標頭的行只是額外的資訊,而不是衝突的指示。它實際上是確認配置是正確的。
在暫存環境中,問題被掩蓋了,因為 WCF 服務和 Web 應用程序託管在同一台伺服器上。問題是 Web 應用程序的站點預設配置為對匿名使用者使用本地帳戶 IUSR(或 IUSR_Server)。這是正在傳遞的使用者(我相信它等於 CredentialCache.DefaultNetworkCredentials)。當它們在不同的伺服器上時,伺服器 2 上的 WCF 顯然無法對伺服器 1 使用者進行身份驗證。解決方案在 IIS 中,右鍵點擊匿名身份驗證 > 編輯…> 檢查應用程序池標識(在我的情況下是域帳戶)或輸入特定使用者的域帳戶。