2012-04-30 96 views
1

我有一個.NET WCF客戶端與Java服務器組件交談。服務器端身份驗證是通過配置爲反向代理的中間Apache服務器完成的。在Windows XP上通過Kerberos進行WCF身份驗證

.NET客戶端具有如下配置:

<basicHttpBinding> 
    <binding name="AdministrationServiceImplServiceSoapBinding"> 
      <security mode="TransportCredentialOnly"> 
      <transport clientCredentialType="Windows" proxyCredentialType="Windows" /> 
      </security> 
    </binding> 
</basicHttpBinding> 

Apache的配置爲需要Kerveros認證:

<LocationMatch "^...$"> 
    AuthType Kerberos 
    Krb5Keytab ... 
    KrbServiceName HTTP/hostname 
    KrbMethodNegotiate on 
    KrbMethodK5Passwd off 
    Require valid-user 
    Satisfy All 
</LocationMatch> 

如果我在Windows 7開始我的應用程序,一切正常預期:.NET客戶端使用Kerberos,Apache認證客戶端,我可以使用Spring安全性訪問客戶端憑證。

如果我在Windows XP上啓動我的應用程序,則會收到HTTP 401錯誤消息。看使用Wireshark的網絡通信後,我看到了這樣的情況:

(1)初始試圖不經認證訪問Web服務

POST <path> HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "" 
Host: <host> 
Content-Length: 374 
Expect: 100-continue 
Connection: Keep-Alive 

(2)100從服務器繼續回覆

HTTP/1.1 100 Continue 

(3)來自客戶端的SOAP請求(仍未認證)

(4)給出401響應的服務器

HTTP/1.1 401 Authorization Required 
Server: Apache 
WWW-Authenticate: Negotiate 

(5)客戶端嘗試使用NTLM身份驗證

POST <path> HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "" 
Authorization: Negotiate TlRMTVNTUAABAAAAt4IY4gAAAAAAAAAAAAAAAAAAAAAFASgKAAAADw== 
Host: <host> 
Content-Length: 0 

(6)從服務器401消息(在這裏我們不說話NTLM!)

HTTP/1.1 401 Authorization Required 

(7 )客戶端放棄

當我解碼來自客戶端的Base64協商頭時,它以NTLMSSP\x00開頭,表示客戶端想要進行NTLM驗證儘管配置文件指定了「Windows」(又名Kerberos)進行驗證。

有什麼我可以在客戶端做說服.NET使用Kerberos?如果不是,我的Apache應該返回什麼,以便客戶端知道它應該使用Kerberos?

+0

我發現了一個相關的SO問題,但答案沒有幫助:http://stackoverflow.com/questions/2319001/why-is-kerberos-defaulting-to -ntlm功能於WCF –

回答

0

Windows未使用Kerberos安全服務的正確服務主體名稱(SPN):使用Kerberos時,Windows應在活動目錄中查找SPN HTTP/$servername

可能的錯誤原因是該服務的SPN不存在並且必須創建(參見Kerberos Authentication problems – Service Principal Name (SPN) issues - Part 3)。然而,在我的設置中,SPN確實存在,但Windows以某種方式不檢索它們)。使用KerbTray我確認Windows確實沒有包含HTTP/$servername的Kerberos票據。

解決方案是顯式定義WCF客戶端配置中的SPN。

<endpoint address="http://$servername/Service" /> 

成爲

<endpoint address="http://$servername/Service" /> 
    <identity> 
    <servicePrincipalName value="HTTP/$servername" /> 
    </identity> 
</endpoint>