Partager via


Message Security over Message Queuing

L’exemple MessageSecurity montre comment implémenter une application qui utilise WS-Security avec l’authentification par certificat X.509v3 pour le client et nécessite l’authentification du serveur à l’aide du certificat X.509v3 du serveur sur MSMQ. La sécurité des messages est parfois plus souhaitable pour s’assurer que les messages dans le magasin MSMQ restent chiffrés et que l’application peut effectuer sa propre authentification du message.

Cet exemple est basé sur l’exemple de Liaison MSMQ traitée. Les messages sont chiffrés et signés.

Pour configurer, générer et exécuter l’exemple

  1. Assurez-vous d’avoir effectué la Procédure d’installation unique pour les exemples Windows Communication Foundation.

  2. Si le service est exécuté en premier, il vérifie que la file d’attente est présente. Si la file d’attente n’est pas présente, le service en crée un. Vous pouvez d’abord exécuter le service pour créer la file d’attente, ou en créer un via le Gestionnaire de files d’attente MSMQ. Suivez ces étapes pour créer une file d’attente dans Windows 2008.

    1. Ouvrez le Gestionnaire de serveur dans Visual Studio 2012.

    2. Développez l’onglet Fonctionnalités.

    3. Cliquez avec le bouton droit sur file d’attente de messages privés, puis sélectionnez Nouveau, file d’attente privée.

    4. Activez la case à cocher Transactionnelle.

    5. Entrez ServiceModelSamplesTransacted comme nom de la nouvelle file d’attente.

  3. Pour générer la version C# ou Visual Basic de la solution, suivez les instructions de Génération des exemples Windows Communication Foundation.

Pour exécuter l’exemple sur le même ordinateur

  1. Vérifiez que le chemin d’accès inclut le dossier qui contient Makecert.exe et FindPrivateKey.exe.

  2. Exécutez Setup.bat à partir de l’exemple de dossier d’installation. Cela installe tous les certificats requis pour l’exécution de l’exemple.

    Remarque

    Vérifiez que vous supprimez les certificats en exécutant Cleanup.bat une fois l’exemple terminé. D’autres exemples de sécurité utilisent les mêmes certificats.

  3. Lancez Service.exe à partir de \service\bin.

  4. Lancez Client.exe à partir de \client\bin. L’activité du client s’affiche sur l’application console cliente.

  5. Si le client et le service ne sont pas en mesure de communiquer, consultez Conseils de résolution des problèmes pour les exemples WCF.

Pour exécuter l’exemple sur différents ordinateurs

  1. Copiez les fichiers Setup.bat, Cleanup.batet ImportClientCert.bat sur l’ordinateur de service.

  2. Créez un répertoire sur l’ordinateur client pour les fichiers binaires clients.

  3. Copiez les fichiers de programme client dans le répertoire client sur l’ordinateur client. Copiez également les fichiers Setup.bat, Cleanup.batet ImportServiceCert.bat sur le client.

  4. Sur le serveur, exécutez setup.bat service. L’exécution de setup.bat avec l’argument service crée un certificat de service avec le nom de domaine complet de l’ordinateur et exporte le certificat de service vers un fichier nommé Service.cer.

  5. Modifiez le service.exe.config du service pour refléter le nouveau nom du certificat (dans l'attribut findValue du <serviceCertificate>), identique au nom de domaine complet de l'ordinateur.

  6. Copiez le fichier Service.cer du répertoire de service vers le répertoire client sur l’ordinateur client.

  7. Sur le client, exécutez setup.bat client. L’exécution de setup.bat avec l’argument client crée un certificat client nommé client.com et exporte le certificat client vers un fichier nommé Client.cer.

  8. Dans le fichier Client.exe.config sur l’ordinateur client, modifiez la valeur d’adresse du point de terminaison pour qu’il corresponde à la nouvelle adresse de votre service. Pour ce faire, remplacez localhost par le nom de domaine complet du serveur. Vous devez également modifier le nom de certificat du service de la même façon que le nom de domaine complet de l’ordinateur de service (dans l’attribut findValue dans l’élément defaultCertificate de serviceCertificate sous clientCredentials).

  9. Copiez le fichier Client.cer du répertoire client vers le répertoire de service sur le serveur.

  10. Sur le client, exécutez ImportServiceCert.bat. Cela importe le certificat de service à partir du fichier Service.cer dans le magasin CurrentUser - TrustedPeople.

  11. Sur le serveur, exécutez ImportClientCert.bat, cela importe le certificat client à partir du fichier Client.cer dans le magasin LocalMachine - TrustedPeople.

  12. Sur l'ordinateur de service, lancez Service.exe à partir d'une invite de commandes.

  13. Sur l’ordinateur client, lancez Client.exe à partir de l’invite de commandes. Si le client et le service ne sont pas en mesure de communiquer, consultez Conseils de résolution des problèmes pour les exemples WCF.

Pour nettoyer après l’échantillon

  • Exécutez Cleanup.bat dans le dossier d’exemples une fois que vous avez terminé d’exécuter l’exemple.

    Remarque

    Ce script ne supprime pas les certificats de service sur un client lors de l’exécution de cet exemple sur les ordinateurs. Si vous avez exécuté des exemples Windows Communication Foundation (WCF) qui utilisent des certificats sur des ordinateurs, veillez à effacer les certificats de service installés dans le magasin CurrentUser - TrustedPeople. Pour ce faire, utilisez la commande suivante : certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name> Par exemple : certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.

Exigences

Cet exemple nécessite que MSMQ soit installé et en cours d’exécution.

Montre ce qui suit

Le client chiffre le message à l’aide de la clé publique du service et signe le message à l’aide de son propre certificat. Le service qui lit le message depuis la file d'attente authentifie le certificat client avec le certificat de son magasin de personnes de confiance. Il déchiffre ensuite le message et le transmet à l’opération de service.

Étant donné que le message WCF est transporté en tant que charge utile dans le corps du message MSMQ, le corps reste chiffré dans le magasin MSMQ. Cela sécurise le message contre la divulgation indésirable du message. Notez que MSMQ lui-même ne sait pas si le message qu’il transporte est chiffré.

L’exemple montre comment l’authentification mutuelle au niveau du message peut être utilisée avec MSMQ. Les certificats sont échangés hors bande. Cela est toujours le cas avec l’application mise en file d’attente, car le service et le client n’ont pas besoin d’être opérationnel en même temps.

Description

Les exemples de code du client et du service sont identiques à l’exemple de Liaison MSMQ traitée, à un détail près. Le contrat d’opération est annoté avec le niveau de protection, ce qui suggère que le message doit être signé et chiffré.

// Define a service contract.
[ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
public interface IOrderProcessor
{
    [OperationContract(IsOneWay = true, ProtectionLevel=ProtectionLevel.EncryptAndSign)]
    void SubmitPurchaseOrder(PurchaseOrder po);
}

Pour vous assurer que le message est sécurisé à l’aide du jeton requis pour identifier le service et le client, le App.config contient des informations d’identification.

La configuration du client spécifie le certificat de service pour authentifier le service. Il utilise son magasin LocalMachine comme magasin approuvé pour s’appuyer sur la validité du service. Il spécifie également le certificat client attaché au message pour l’authentification du service du client.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.serviceModel>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity"
                binding="netMsmqBinding"
                bindingConfiguration="messageSecurityBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor"
                behaviorConfiguration="ClientCertificateBehavior" />
    </client>

    <bindings>
        <netMsmqBinding>
            <binding name="messageSecurityBinding">
                <security mode="Message">
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </netMsmqBinding>
    </bindings>

    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <!--
        The clientCredentials behavior allows one to define a certificate to present to a service.
        A certificate is used by a client to authenticate itself to the service and provide message integrity.
        This configuration references the "client.com" certificate installed during the setup instructions.
        -->
          <clientCredentials>
            <clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
            <serviceCertificate>
                <defaultCertificate findValue="localhost" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              <!--
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
            is in the user's Trusted People store, then it is trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the
            sample can be run without having to have certificates issued by a certification authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this
            setting should be carefully considered before using PeerOrChainTrust in production code.
            -->
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

Notez que le mode de sécurité est défini sur Message et que ClientCredentialType est défini sur Certificat.

La configuration du service inclut un comportement de service qui spécifie les informations d’identification du service utilisées lorsque le client authentifie le service. Le nom de l’objet du certificat de serveur est spécifié dans l’attribut findValue dans le <serviceCredentials>.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <!-- Use appSetting to configure MSMQ queue name. -->
    <add key="queueName" value=".\private$\ServiceModelSamplesMessageSecurity" />
  </appSettings>

  <system.serviceModel>
    <services>
      <service
          name="Microsoft.ServiceModel.Samples.OrderProcessorService"
          behaviorConfiguration="PurchaseOrderServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/ServiceModelSamples/service"/>
          </baseAddresses>
        </host>
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity"
                  binding="netMsmqBinding"
                  bindingConfiguration="messageSecurityBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
        <!-- The mex endpoint is exposed at http://localhost:8000/ServiceModelSamples/service/mex. -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
        <netMsmqBinding>
            <binding name="messageSecurityBinding">
                <security mode="Message">
                    <message clientCredentialType="Certificate" />
                </security>
            </binding>
        </netMsmqBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="PurchaseOrderServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <!--
               The serviceCredentials behavior allows one to define a service certificate.
               A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
               This configuration references the "localhost" certificate installed during the setup instructions.
          -->
          <serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
            <clientCertificate>
                <certificate findValue="client.com" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              <!--
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
            is in the user's Trusted People store, then it is trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the
            sample can be run without having to have certificates issued by a certification authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this
            setting should be carefully considered before using PeerOrChainTrust in production code.
            -->
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

</configuration>

L’exemple montre comment contrôler l’authentification à l’aide de la configuration et comment obtenir l’identité de l’appelant à partir du contexte de sécurité, comme illustré dans l’exemple de code suivant :

// Service class which implements the service contract.
// Added code to write output to the console window.
public class OrderProcessorService : IOrderProcessor
{
    private string GetCallerIdentity()
    {
        // The client certificate is not mapped to a Windows identity by default.
        // ServiceSecurityContext.PrimaryIdentity is populated based on the information
        // in the certificate that the client used to authenticate itself to the service.
        return ServiceSecurityContext.Current.PrimaryIdentity.Name;
    }

    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
    public void SubmitPurchaseOrder(PurchaseOrder po)
    {
        Console.WriteLine("Client's Identity {0} ", GetCallerIdentity());
        Orders.Add(po);
        Console.WriteLine("Processing {0} ", po);
    }
  //…
}

Lors de l’exécution, le code du service affiche l’identification du client. Voici un exemple de sortie du code de service :

The service is ready.
Press <ENTER> to terminate service.

Client's Identity CN=client.com; ECA6629A3C695D01832D77EEE836E04891DE9D3C
Processing Purchase Order: 6536e097-da96-4773-9da3-77bab4345b5d
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Commentaires

  • Création du certificat client.

    La ligne suivante dans le fichier batch crée le certificat client. Le nom du client spécifié est utilisé dans le nom de l’objet du certificat créé. Le certificat est stocké dans le store My à l'emplacement du store CurrentUser.

    echo ************
    echo making client cert
    echo ************
    makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
    
  • Installation du certificat client dans le magasin de certificats approuvé du serveur.

    La ligne suivante du fichier batch copie le certificat client dans le magasin TrustedPeople du serveur afin que le serveur puisse prendre les décisions d’approbation ou de non-confiance pertinentes. Pour qu’un certificat installé dans le magasin TrustedPeople soit approuvé par un service Windows Communication Foundation (WCF), le mode de validation de certificat client doit être défini sur PeerOrChainTrust ou PeerTrust valeur. Consultez l’exemple de configuration de service précédent pour savoir comment procéder à l’aide d’un fichier de configuration.

    echo ************
    echo copying client cert to server's LocalMachine store
    echo ************
    certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople
    
  • Création du certificat de serveur.

    Les lignes suivantes du fichier batch Setup.bat créent le certificat de serveur à utiliser :

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    

    La variable %SERVER_NAME% spécifie le nom du serveur. Le certificat est stocké dans le magasin LocalMachine. Si le fichier batch d’installation est exécuté avec un argument de service (tel que setup.bat service), l'%SERVER_NAME% contient le nom de domaine complet de l’ordinateur. Sinon, il est défini par défaut sur localhost.

  • Installation du certificat de serveur dans le magasin de certificats approuvé du client.

    La ligne suivante copie le certificat de serveur dans le magasin de personnes de confiance du client. Cette étape est requise, car les certificats générés par Makecert.exe ne sont pas implicitement approuvés par le système client. Si vous disposez déjà d’un certificat rooté dans un certificat racine approuvé par le client( par exemple, un certificat émis par Microsoft), cette étape de remplissage du magasin de certificats client avec le certificat de serveur n’est pas nécessaire.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    

    Remarque

    Si vous utilisez une version anglaise non américaine de Microsoft Windows, vous devez modifier le fichier Setup.bat et remplacer le nom du compte « NT AUTHORITY\NETWORK SERVICE » par votre équivalent régional.