2009-08-18 9 views
8

J'ai suivi de nombreux articles msdn et le guidage codeplex, mais je ne peux pas utiliser WCF pour fonctionner avec l'authentification et la délégation Kerberos et j'apprécierais un peu d'aide.Authentification WCF et Kerberos

Configuration

J'ai le service WCF dans un site Web IIS sur une machine distante

  • IIS 6.0 sur Windows 2003 R2 - SP 2
  • Le SPN de la machine a été ajoutée (http/myserver & & http/myserver: 8080)
  • Un compte AD a été créé pour le pool d'applications IIS
  • Le compte AD a le réglage, autoriser la délégation (pour Kerberos), la valeur true

J'utilise Brian Booth's debug site sur 8080 et le site passe à toutes les exigences pour la délégation Kerberos. Le site IIS de débogage a désactivé l'authentification anonyme et l'authentification Windows intégrée. Je ai mis en miroir ces paramètres pour le site hébergeant le service WCF en miroir.

Web Service - Config Web (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 - Méthode Web

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

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

Erreur d'application

L'erreur suivante se produit lorsque mon application de test, une application WinForms, tente d'appeler la méthode Web:

« La requête HTTP est non autorisée avec système d'authentification client 'Anonymous' . L'en-tête d'authentification reçu du serveur était 'Negotiate, NTLM' «

Event Log

L'erreur suivante est dans le journal des événements:.

Exception: système .ServiceModel.ServiceActivationException: Le service '/Service.svc' ne peut pas être activé en raison d'une exception tion. Le message d'exception est: Les paramètres de sécurité pour ce service nécessitent une authentification 'Anonyme' mais il n'est pas activé pour l'application IIS qui héberge ce service.

Ce que je ne comprends pas. Le but de ce service est de ne pas autoriser l'authentification anonyme, chaque utilisateur/requête doit être authentifié à l'aide de tickets Kerberos, puis transmis aux autres machines.

Comment dois-je configurer ce service WCF pour l'authentification et la délégation Kerberos?

Révision 1

Après avoir lu this SO question j'ai supprimé le point final de métadonnées. Cela n'a pas résolu le problème.

Révision 2

Après plus des recherches que j'ai trouvé quelques messages suggérant de changer wsHttpBinding à basicHttpBinding. La modification de cette partie du fichier web.config a été incluse ci-dessous et le point de terminaison du service a été mis à jour pour faire référence à cette liaison.

Web Service - Config Web (révisée)

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

App Client - App Config (révisée)

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

erreur (révisée)

Le courant erreur semble contenir un autel Kerberos en-tête de recherche.

La requête HTTP est non autorisée avec système d'authentification client 'Négociez'. L'en-tête d'authentification reçue du serveur était « Négociez SOMEHUGESCARYKEYHERE

+1

Remarque, j'ai posté et supprimé quelque chose de similaire hier, cet article comprend des révisions basées sur plus de recherche et devrait être plus propre à lire. – blu

+1

J'ai ajouté la config d'application révisée basée sur les commentaires de marc_s. – blu

Répondre

3

Quelque chose que je remarque: le client et configuration du serveur ne semblent pas d'accord sur le mode de sécurité.

Dans la section d'origine, vous avez <security>..... dans web.config (omis le mode = "message"), et <security mode="Message"> côté client.

Après votre modification, il semble que le côté client est inchangé, mais le serveur (web.config) contient maintenant <security mode="TransportCredentialOnly">.

La question est vraiment: pouvez-vous garantir qu'il n'y aura jamais qu'une étape réseau entre le client et le serveur appelé? C'est à dire. est-ce derrière un pare-feu d'entreprise? Dans ce cas, je recommanderais la liaison netTcp avec <security mode="Transport"> aux deux extrémités. Si ce n'est pas le cas, vous pouvez utiliser wsHttpBinding (qui prend en charge plus de fonctions de sécurité et de fiabilité, mais plus lent et "plus lourd") ou basicHttpBinding. Dans ce cas, vous devrez utiliser <security mode="Message"> aux deux extrémités et authentifier le service avec un certificat (de sorte que le service et le client aient un «secret» commun à utiliser pour le chiffrement).Je voudrais essayer de laisser de côté les parties d'emprunt d'identité pour le début et juste obtenir la communication de base et l'authentification mutuelle entre le service et le client opérationnel - une fois que c'est en place, vous pouvez commencer à ajouter les bits d'emprunt d'identité, et vous pouvez toujours vous rabattre sur une configuration connue qui fonctionne.

David Sackstein a une great series of blog posts expliquant les cinq scénarios de sécurité gourou de l'industrie Juval Lowy a identifié (dans son livre Programming WCF - la Bible WCF) comme le plus commun et le plus utile - afin de limiter le nombre de combinaisons possibles de paramètres vous pourriez vouloir modifier. L'un d'entre eux est un scénario «Internet» qui s'appliquerait probablement ici, si votre service est tourné vers l'extérieur.

Marc

+1

Merci pour la réponse. Je n'ai pas inclus le code client mis à jour, j'ai pensé que la question avait assez d'encombrement tel qu'il est. Je vais passer en revue les informations que vous avez fournies, merci. – blu

+1

"authentifiez le service avec un certificat", c'est quelque chose que quelqu'un essaye ici d'éviter. Nous espérions utiliser des tickets Kerberos pour authentifier les utilisateurs et les déléguer à des machines back-end telles que SP et SQL. – blu

7

Pour moi, la configuration actuelle fonctionne:

Sur le serveur:

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

Définissez l'attribut suivant sur toutes les méthodes pour la WCF:

[OperationBehavior(Impersonation = ImpersonationOption.Required)] 

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

Qu'en est-il de vos paramètres IIS pour les méthodes d'authentification? L'accès anonyme est-il désactivé? – Jonathan

+1

J'ai l'authentification Windows et l'accès anonyme activés. Mais vous aurez besoin uniquement d'Anonymous, lors de l'ajout du point de terminaison mex (IMetadataExchange) pour votre service. –

1

Vous devriez tenter votre configuration initiale et assurez-vous de définir l'IIS pour être l'authentification anonyme et fenêtres à la même raison temps.Le est quand vous utilisez la sécurité par défaut wsHttpBinding est la sécurité des messages et il n'y a pas de sécurité de transport définie, sauf si vous voulez faire https. SO Clr indique qu'il a besoin d'authentification anonyme activée sur IIS.

2

Vous devez spécifier une behaviorConfiguration dans votre configuration client. SVCUtil ne génère pas automatiquement. Cela a résolu mon problème et j'utilise maintenant Kerberos avec succès. C'était une mission cependant!

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