2009-08-18 19 views
8

Ho seguito numerosi articoli msdn e la guida di codeplex ma non riesco a far funzionare WCF con l'autenticazione Kerberos e la delega e apprezzerei un piccolo aiuto.Autenticazione WCF e Kerberos

Setup

Ho il servizio WCF in un sito Web IIS su una macchina remota

  • IIS 6.0 su Windows 2003 R2 - SP 2
  • L'SPN per la macchina è stata aggiunta (http/myserver & & http/myserver: 8080)
  • Un account AD è stato creato per il pool di applicazioni IIS
  • L'account AD ha l'impostazione, consentire la delega (per Kerberos), impostata su true

Sto usando Brian Booth's debug site sul 8080 e il sito ha superato tutti i requisiti per la delega Kerberos. Il sito di debug di IIS ha l'autenticazione anonima disattivata e l'autenticazione integrata di Windows attiva.

Ho effettuato il mirroring di queste impostazioni sul sito che ospita il servizio WCF.

Web Service - Web Config (Original)

<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 Service - Metodo Web

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

client App - App Config

<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> 

Application Error

Il seguente errore si verifica quando la mia applicazione di test, un'applicazione WinForms, tenta di chiamare il metodo web:

"La richiesta HTTP non è autorizzato con cliente schema di autenticazione 'Anonymous' . L'intestazione di autenticazione ricevuto dal server è stato 'Negotiate, NTLM' "

Registro eventi

Il seguente errore è nel registro eventi:.

Eccezione: sistema .ServiceModel.ServiceActivationException: Il servizio '/Service.svc' non può essere attivato a causa di un'eccezione durante compila zione. Il messaggio di eccezione è: le impostazioni di sicurezza per questo servizio richiedono l'autenticazione "anonima" ma non è abilitato per l'applicazione IIS che ospita questo servizio.

Che non capisco. L'intero punto di questo servizio è quello di non consentire l'autenticazione anonima, ogni utente/richiesta deve essere autenticato utilizzando i ticket Kerberos, quindi passandoli attraverso altre macchine.

Come devo configurare questo servizio WCF per l'autenticazione e la delega Kerberos?

Revisione 1

Dopo aver letto this SO question ho rimosso l'endpoint metadati. Questo non ha risolto il problema.

Revisione 2

Dopo più ricercando ho trovato alcuni post che suggeriscono di cambiare wsHttpBinding a basicHttpBinding. La modifica a quella parte di web.config è stata inclusa di seguito e l'endpoint del servizio è stato aggiornato per fare riferimento a tale associazione.

Web Service - Web Config (riveduta) App

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

cliente - App Config (Revised)

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

Error (riveduta)

L'attuale l'errore sembra che contenga un Kerberos authe intestazione

La richiesta HTTP non è autorizzato con schema di autenticazione del client 'Negoziare'. L'intestazione di autenticazione ricevuto dal server è stato 'Negoziare SOMEHUGESCARYKEYHERE

+1

Nota, ho postato e cancellato qualcosa di simile ieri, questo post include revisioni basate su ulteriori ricerche e dovrebbe essere più pulito da leggere. – blu

+1

Ho aggiunto la configurazione dell'app modificata in base al feedback di marc_s. – blu

risposta

3

Qualcosa che ho notato: il client e configurazione del server non sembrano essere d'accordo sulla modalità di sicurezza.

Nella sezione originale, si ha <security>..... nel web.config (omesso il modo = "messaggio") e <security mode="Message"> sul lato client.

Dopo la modifica, sembra che il lato client sia invariato, ma il server (web.config) ora contiene <security mode="TransportCredentialOnly">.

La domanda è davvero: si può garantire che ci sarà sempre un solo segmento di rete tra il client e il server che viene chiamato? Cioè è dietro un firewall aziendale? In tal caso, consiglierei netTcp binding con <security mode="Transport"> su entrambe le estremità.

In caso contrario, è possibile utilizzare wsHttpBinding (che supporta più funzioni di sicurezza e affidabilità, ma è più lento e "pesante") o basicHttpBinding. In tal caso, è necessario utilizzare <security mode="Message"> su entrambe le estremità e autenticare il servizio con un certificato (in modo che il servizio e il client abbiano un "segreto" comune da utilizzare per la crittografia).

Vorrei provare a escludere le parti di impersonificazione per l'inizio e ottenere la comunicazione di base e l'autenticazione reciproca tra servizio e client prima e in esecuzione, una volta che è a posto, è possibile iniziare ad aggiungere i bit di rappresentazione, e puoi sempre ricorrere a una configurazione nota che funziona.

David Sackstein ha un great series of blog posts che spiega i cinque scenari di sicurezza che l'industria guru Juval Lowy ha identificato (nel suo Programming WCF libro - WCF Bibbia) come il più comune e più utile - al fine di limitare il numero di possibili combinazioni di parametri potresti voler modificare. Uno di questi è uno scenario "Internet" che probabilmente si applicherebbe qui, se il tuo servizio è rivolto verso l'esterno.

Marc

+1

Grazie per la risposta. Non ho incluso il codice client aggiornato, ho pensato che la domanda avesse abbastanza confusione. Troverò le informazioni che hai fornito, grazie. – blu

+1

"autenticate il servizio con un certificato", questo è qualcosa che qualcuno sta cercando di evitare. Speravamo di utilizzare dritti ticket Kerberos per autenticare gli utenti e delegare fino a macchine back-end come SP e SQL. – blu

7

Per me l'impostazione corrente funziona:

sul server:

<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> 

Impostare il seguente attributo su tutti i metodi per la WCF:

[OperationBehavior(Impersonation = ImpersonationOption.Required)] 

Sul client:

<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, Sven

+1

E le impostazioni IIS per i metodi di autenticazione? L'accesso anonimo è disattivato? – Jonathan

+1

Ho abilitato l'autenticazione di Windows e l'accesso anonimo. Ma avrai bisogno solo di Anonymous, quando aggiungi l'endpoint mex (IMetadataExchange) per il tuo servizio. –

1

si dovrebbe tentare la configurazione iniziale e assicurarsi di impostare l'IIS di essere l'autenticazione anonima e finestre allo stesso motivo time.The è quando si utilizza la protezione wsHttpBinding di default è la sicurezza dei messaggi e non è definita alcuna sicurezza di trasporto a meno che non si voglia fare https. SO Clr afferma di aver bisogno dell'autenticazione anonima attivata su IIS.

2

È necessario specificare un comportamentoConfigurazione nella configurazione del client. SVCUtil non genera automaticamente. Questo ha risolto il mio problema e ora sto utilizzando Kerberos con successo. Era una missione però!

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