2011-10-01 3 views
3

J'essaie de créer un service WCF4 hébergé sur IIS qui utilisera des certificats X.509 pour la sécurité des messages et SSL avec l'authentification mutuelle requise pour la sécurité du transport (projet spécification nécessite l'utilisation de WS-Security et SSL, AFAIK seul est généralement le chemin à parcourir, mais peu importe).WCF 4 - TransportWithMessageCredential utilisant des certificats X.509 pour le transport et la sécurité des messages

J'ai effectué mon TestRootCA et l'ai utilisé pour délivrer un certificat de serveur (localhost) et un certificat client (TestUser). Je voulais d'abord établir et tester la sécurité du transport uniquement, donc j'ai configuré IIS pour utiliser https, certificat SSL configuré (cert localhost que j'ai fait), et configuré IIS à besoin un certificat client des clients. J'ai ensuite modifié le service web.config, créé le fichier svcutil.conf correspondant et lancé svcutil qui a réussi à créer la classe proxy client et app.config pour mon application WinForms de test. J'ai mis le certificat lors de la création du client proxy en appelant:

var client = new ServiceClient(); 
client.ClientCredentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.CurrentUser, System.Security.Cryptography.X509Certificates.StoreName.My, System.Security.Cryptography.X509Certificates.X509FindType.FindBySubjectDistinguishedName, "CN=TestUser"); 
MessageBox.Show(client.GetData(42)); 

Jusqu'ici tout va bien. Mais lorsque je modifie web.config du service pour utiliser TrasportWithMessageCredential (au lieu de Transport) et que je spécifie "Certificate" comme clientCredentialType pour la sécurité des messages, j'obtiens HTTP 403 - The HTTP request was forbidden with client authentication scheme 'Anonymous', même si j'ai spécifié "Certificate".

Mon web.config finale ressemble à ceci:

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
      <binding name="wsHttpEndpointBinding"> 
       <security mode="TransportWithMessageCredential"> 
        <transport clientCredentialType="Certificate"/> 
        <message clientCredentialType="Certificate"/> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <services> 
     <service behaviorConfiguration="serviceBehavior" name="Service"> 
      <endpoint binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="wsHttpEndpoint" contract="IService" /> 
      <endpoint address="mex" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpointBinding" name="mexEndpoint" contract="IMetadataExchange" /> 
     </service> 
    </services> 
    <behaviors> 
     <serviceBehaviors> 
      <behavior name="serviceBehavior"> 
       <serviceMetadata httpsGetEnabled="true" /> 
       <serviceDebug includeExceptionDetailInFaults="true" /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
</system.serviceModel> 

et mon app.conf client:

<system.serviceModel> 
    <bindings> 
     <wsHttpBinding> 
      <binding name="wsHttpEndpoint" 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="TransportWithMessageCredential"> 
        <transport clientCredentialType="Certificate"/> 
        <message clientCredentialType="Certificate"/> 
       </security> 
      </binding> 
     </wsHttpBinding> 
    </bindings> 
    <client> 
     <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" /> 
    </client> 
</system.serviceModel> 

Toutes les idées?

EDIT:

J'ai réussi à le faire fonctionner en changeant les paramètres SSL IIS pour le certificat client de exigent-acceptent. Il semble que lorsque j'introduis la sécurité des messages en utilisant des certificats sur la sécurité de transport en utilisant SSL, le client utilise le certificat pour la signature du message mais pas l'authentification pour l'authentification mutuelle sur SSL (il essaie de se connecter comme anonyme même s'il a un certificat assigné).

Je ne sais pas pourquoi cela se produit, j'aimerais un commentaire d'un expert :).

Répondre

1

Comme il est indiqué dans la question, je l'ai eu de travail en changeant les paramètres IIS SSL pour les certificats clients require-accept.Ensuite, dans le point d'entrée du service, je vérifie de manière programmatique le certificat de l'utilisateur distant (s'il n'est pas nul et valide).

1

Vous devez spécifier les certificats à utiliser pour chiffrer le message dans la section de comportement puisque ceux-ci pourraient être différents que ceux utilisés pour établir le canal https

il ressemblerait à ceci dans le serveur

<system.serviceModel> 
<behaviors>  
    <serviceBehaviors>  
     <behavior name="serviceBehavior"> 
     <serviceCredentials> 
     <serviceCertificate findValue="ServerCertificate" 
          storeLocation="CurrentUser" 
          storeName="My" 
          x509FindType="FindByIssuerName" /> 
     <clientCertificate> 
      <certificate findValue ="ClientCertificate" 
         storeLocation="CurrentUser" 
          storeName="My" 
          x509FindType="FindByIssuerName"/> 
      <authentication certificateValidationMode ="PeerTrust"/> 
     </clientCertificate> 
     </serviceCredentials> 
      <serviceMetadata httpsGetEnabled="true" />  
      <serviceDebug includeExceptionDetailInFaults="true" />  
     </behavior>  
    </serviceBehaviors>  
</behaviors> 
</system.serviceModel> 

et faire la même chose dans le client, qui se présente comme suit

<system.serviceModel>   
    <bindings>   
     <wsHttpBinding>   
      <binding name="wsHttpEndpoint" 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="TransportWithMessageCredential">   
        <transport clientCredentialType="Certificate"/>   
        <message clientCredentialType="Certificate"/>   
       </security>   
      </binding>   
     </wsHttpBinding>   
    </bindings> 
<behaviors>  
    <endpointBehaviors>   
    <behavior name="ClientCredentialsBehavior"> 
     <clientCredentials>    
     <clientCertificate x509FindType="FindBySubjectName" 
          findValue="ClientCertificate" 
          storeLocation="CurrentUser" 
          storeName="My"/> 
     <serviceCertificate> 
      <defaultCertificate x509FindType="FindBySubjectName" 
           findValue="ServerCertificate" 
           storeLocation="CurrentUser" 
           storeName="My"/> 
     </serviceCertificate> 
     </clientCredentials> 
    </behavior> 
    </endpointBehaviors> 
</behaviors> 

    <client>   
     <endpoint address="https://localhost/WCFTestService/Service.svc" binding="wsHttpBinding" bindingConfiguration="wsHttpEndpoint" contract="IService" name="wsHttpEndpoint" behaviorConfiguration="ClientCredentialsBehavior" />   
    </client>   
</system.serviceModel> 

bien sûr, vous devez définir le bon emplacement et le nom du cert ificates, dans le serveur et le client.

J'espère que cela aide encore

+0

N'ont pas essayé ceci, mais même si cela fonctionnerait, la nécessité de spécifier un * certificat * client * dans la * configuration * de serveur est un briseur d'affaire. Le serveur ne connaît pas le certificat client à l'avance (et il y a beaucoup de clients différents), il utilise la confiance de la chaîne (si le isssuer du client cert est valide, le cert client est accepté et utilisé comme identification). –

+0

Cela a corrigé l'erreur que je recevais "La requête HTTP était interdite avec le schéma d'authentification client 'Anonymous'". J'ai seulement eu les certificats de serveur spécifiés. Merci – Nanook

Questions connexes