2009-08-18 252 views
8

我遵循了許多msdn文章和codeplex指導,但無法讓WCF與Kerberos身份驗證和委派一起工作,並希望得到一些幫助。WCF和Kerberos身份驗證

設置

我有一個IIS網站的WCF服務的遠程機

  • 在IIS 6.0在Windows 2003 R2 - SP 2
  • 的SPN機已添加(http/myserver & & http/myserver:8080)
  • 爲IIS應用程序池創建了一個AD帳戶
  • 廣告帳戶的設置,允許委派(使用Kerberos),設置爲true

我使用8080 Brian Booth's debug site和站點通行證Kerberos委派的所有要求。調試IIS站點關閉了匿名身份驗證,並啓用了集成Windows身份驗證。

我已將這些設置鏡像到承載WCF服務的網站。

Web服務 - Web配置(原件)

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
      <binding name="WsHttpBindingConfig"> 
       <security> 
        <message negotiateServiceCredential="true" /> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="ServiceBehavior" name="Service">  
      <endpoint address="" 
       binding="wsHttpBinding" 
       bindingConfiguration="WsHttpBindingConfig" 
       contract="IService">  
       <identity>  
        <servicePrincipalName value="http/myserver" />  
        <dns value="" />  
       </identity>  
      </endpoint>  
      <endpoint address="mex" 
       binding="mexHttpBinding" 
       contract="IMetadataExchange" />  
     </service>  
    </services>  
    <behaviors>  
     <serviceBehaviors>  
      <behavior name="ServiceBehavior">  
       <serviceMetadata httpGetEnabled="true"/>  
       <serviceDebug includeExceptionDetailInFaults="true"/>  
       <serviceAuthorization 
        impersonateCallerForAllOperations="true" />  
      </behavior>  
     </serviceBehaviors>  
    </behaviors>  
</system.serviceModel> 

Web服務 - Web方法

[OperationBehavior(Impersonation = ImpersonationOption.Required)] 
public string GetCurrentUserName() 
{ 
    string name = WindowsIdentity.GetCurrent().Name; 
    return name; 
} 

客戶端應用 - 應用程序配置

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
      <binding name="WSHttpBinding_IService" 
       ... /> 
       ... 
       <security mode="Message"> 
        <transport clientCredentialType="Windows" 
         proxyCredentialType="None" 
         realm="" /> 
        <message clientCredentialType="Windows" 
         negotiateServiceCredential="true" 
         algorithmSuite="Default" 
         establishSecurityContext="true" /> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="http://myserver/Service.svc" 
      binding="wsHttpBinding" 
      bindingConfiguration="WSHttpBinding_IService" 
      contract="KerberosService.IService" 
      name="WSHttpBinding_IService"> 
      <identity> 
       <servicePrincipalName value="http/myserver" /> 
      </identity> 
     </endpoint> 
    </client> 
</system.serviceModel> 

應用程序錯誤

當我的測試應用程序,WinForms應用程序,試圖調用web方法發生以下錯誤:

「的HTTP請求是未經授權的 客戶認證方案 ‘匿名’ 。認證頭從服務器接收 是 '協商,NTLM'「

事件日誌

下面的錯誤是在事件日誌中:

例外: 系統.ServiceModel.ServiceActivationException: 由於 compila中的異常,服務「/Service.svc」不能爲 激活灰。 的例外消息是:此服務的安全設置 需要「匿名」身份驗證,但 未啓用託管此服務的IIS 應用程序。

我不明白。此服務的重點是不允許匿名身份驗證,每個用戶/請求必須使用Kerberos票據進行身份驗證,然後將其傳遞到其他計算機。

我應該如何配置此WCF服務以進行Kerberos身份驗證和委派?

修訂1

讀取this SO question後我刪除元數據端點。這並沒有解決這個問題。

修訂2

更多研發後,我發現了幾個帖子建議改變的wsHttpBinding到basicHttpBinding的。對web.config的那部分的修改已經包含在下面,並且服務端點已經被更新以引用該綁定。

Web服務 - Web配置(修訂)

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

客戶端應用 - 應用程序配置(修訂)

<!-- ... --> 
<security mode="TransportCredentialOnly"> 
    <transport clientCredentialType="Windows" 
     proxyCredentialType="Windows" 
     realm="" /> 
    <message clientCredentialType="UserName" 
     algorithmSuite="Default" /> 
</security> 
<!-- ... --> 

錯誤(修訂)

目前錯誤看起來像包含Kerberos驗證碼驗證標頭。

HTTP請求是未經授權的客戶端 認證方案 '協商'。從服務器接收認證頭 是 「協商SOMEHUGESCARYKEYHERE

+1

請注意,我發佈和刪除了類似的東西昨天,這篇文章包括基於更多的研究修訂,應該更清晰的閱讀。 – blu 2009-08-18 18:02:22

+1

我根據marc_s的反饋添加了修改後的應用配置。 – blu 2009-08-18 21:06:44

回答

3

東西我注意到:在客戶端和服務器的配置似乎並沒有在安全模式達成一致。

在原始部分中,您在web.config中有<security>.....(省略了mode =「message」),並且在客戶端有<security mode="Message">

編輯完成後,似乎客戶端不變,但服務器(web.config)現在包含<security mode="TransportCredentialOnly">

問題的確是:你能保證在客戶端和被調用的服務器之間只有一個網絡分支嗎?即這是企業防火牆的後面嗎?在這種情況下,我會推薦netTcp綁定兩端的<security mode="Transport">

如果情況並非如此,那麼wsHttpBinding(支持更多安全性和可靠性功能,但速度更慢,更「重」)或basicHttpBinding可以。在這種情況下,您必須在兩端使用<security mode="Message">,並使用證書對服務進行身份驗證(以便服務和客戶端具有用於加密的公共「祕密」)。

我會嘗試在開始時忽略模擬部分,並首先獲取服務和客戶端之間的基本通信和相互身份驗證,並首先運行 - 一旦到位,您可以開始向其添加模擬位,並且您可以始終使用已知的配置工作。

David Sackstein有一個great series of blog posts解釋行業大師Juval Lowy已經確定的五個安全情景(在他的Programming WCF書--WCF聖經中)是最常見也是最有用的 - 爲了限制可能的參數組合數量你可能想調整。其中之一是一個「互聯網」的情況,如果你的服務是面向外部的話,這種情況可能適用於此。

馬克

+1

感謝您的回覆。我沒有包含更新的客戶端代碼,我認爲這個問題已經足夠混亂了。我會翻閱你提供的信息,謝謝。 – blu 2009-08-18 21:02:53

+1

「用證書驗證服務」,這是某人在嘗試避免的情況。我們希望使用直接的Kerberos票證對用戶進行身份驗證,並一直到SP和SQL等後端機器進行委派。 – blu 2009-08-18 21:08:27

7

對我來說,當前的設置沒有問題:

在服務器上:

<system.serviceModel> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="wsHttpBindingConf" useDefaultWebProxy="true"/> 
    </wsHttpBinding> 
    </bindings> 

    <services> 
    <service behaviorConfiguration="returnFaults" name="Epze.BusinessLayer.ZeitManager"> 
     <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpBindingConf" contract="Epze.Contract.IZeitManager"/> 
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/> 
    </service> 
    </services> 

    <behaviors> 
    <serviceBehaviors> 
     <behavior name="returnFaults"> 
      <serviceMetadata httpGetEnabled="true"/> 
      <serviceDebug includeExceptionDetailInFaults="true"/> 
      <serviceAuthorization impersonateCallerForAllOperations="true"/> 
     </behavior> 
    </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 

設置上的WCF所有方法如下屬性:

[OperationBehavior(Impersonation = ImpersonationOption.Required)] 

在客戶端:

<system.serviceModel> 
    <bindings> 
    <wsHttpBinding> 
     <binding name="WSHttpBinding_IZeitManager" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false"> 
      <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384"/> 
      <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false"/> 
      <security mode="Message"> 
       <transport clientCredentialType="Windows" proxyCredentialType="None" realm=""/> 
       <message clientCredentialType="Windows" negotiateServiceCredential="true" algorithmSuite="Default" establishSecurityContext="true"/> 
      </security> 
     </binding> 
    </wsHttpBinding> 
    </bindings> 

    <behaviors> 
    <endpointBehaviors> 
     <behavior name="Delegation"> 
     <clientCredentials> 
      <windows allowedImpersonationLevel="Delegation" /> 
     </clientCredentials> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors>   

    <client> 
    <endpoint address="http://server.mydomain.net/ePZEsvc/ZeitManager.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IZeitManager" 
       contract="External.Epze.IZeitManager" name="WSHttpBinding_IZeitManager" behaviorConfiguration="Delegation"> 
     <identity> 
      <servicePrincipalName value="HOST/localhost"/> 
     </identity>      
    </endpoint> 
    </client> 
</system.serviceModel> 

HTH,斯文

+1

身份驗證方法的IIS設置如何?匿名訪問是否關閉? – Jonathan 2011-06-10 09:38:08

+1

我啓用了Windows身份驗證和匿名訪問。但是,在爲您的服務添加mex(IMetadataExchange)端點時,您只需要匿名。 – 2011-06-14 14:11:03

1

你應該試試你的初始配置,並確保設置IIS是在同一time.The原因匿名和Windows身份驗證時,您正在使用的wsHttpBinding默認的安全是信息安全除非您想要執行https,否則沒有定義傳輸安全性。 SO Clr聲明它需要在IIS上啓用匿名身份驗證。

2

您需要在客戶端配置中指定一個behaviorConfiguration。 SVCUtil不會自動生成。這解決了我的問題,我現在成功地使用了Kerberos。儘管這是一個使命!

<client>   
    <endpoint address="..."    
    binding="customBinding" bindingConfiguration="..."    
    contract="..." name="..." behaviorConfiguration="ImpersonationBehavior" />     
    </client>   
    <behaviors> 
     <endpointBehaviors>    
     <behavior name="ImpersonationBehavior">    
       <clientCredentials>     
       <windows allowedImpersonationLevel="Impersonation"/>      </clientCredentials>    
    </behavior>      
    </endpointBehaviors>     
    </behaviors>