Condividi tramite


Sicurezza dei messaggi nell'ambito del Message Queuing

L'esempio di MessageSecurity illustra come implementare un'applicazione che usa WS-Security con l'autenticazione del certificato X.509v3 per il client e richiede l'autenticazione server usando il certificato X.509v3 del server su MSMQ. La sicurezza dei messaggi è talvolta più utile per garantire che i messaggi nell'archivio MSMQ rimangano crittografati e che l'applicazione possa eseguire la propria autenticazione del messaggio.

Questo esempio si basa sull'esempio dell'associazione MSMQ transazionata. I messaggi vengono crittografati e firmati.

Per configurare, compilare ed eseguire l'esempio

  1. Assicurati di aver eseguito la procedura di installazione di One-Time per gli esempi di Windows Communication Foundation.

  2. Se il servizio viene eseguito per primo, verifica che la coda sia presente. Se la coda non è presente, il servizio ne creerà uno. È possibile eseguire prima il servizio per creare la coda oppure crearne una tramite Gestione code MSMQ. Seguire questa procedura per creare una coda in Windows 2008.

    1. Aprire Server Manager in Visual Studio 2012.

    2. Espandi la scheda funzionalità.

    3. Fare clic con il pulsante destro del mouse code di messaggi privati e selezionare Nuovo, coda privata.

    4. Selezionare la casella transazionale.

    5. Inserire ServiceModelSamplesTransacted come nome della nuova coda.

  3. Per compilare l'edizione C# o Visual Basic della soluzione, seguire le istruzioni in Compilazione degli esempi di Windows Communication Foundation.

Per eseguire l'esempio nello stesso computer

  1. Assicurarsi che il percorso includa la cartella contenente Makecert.exe e FindPrivateKey.exe.

  2. Eseguire Setup.bat dalla cartella di installazione di esempio. Vengono installati tutti i certificati necessari per l'esecuzione dell'esempio.

    Nota

    Assicurarsi di rimuovere i certificati eseguendo Cleanup.bat al termine dell'esempio. Altri esempi di sicurezza usano gli stessi certificati.

  3. Avvia Service.exe da \service\bin.

  4. Avvia Client.exe da \client\bin. L'attività client viene visualizzata nell'applicazione console client.

  5. Se il client e il servizio non sono in grado di comunicare, vedere Suggerimenti per la risoluzione dei problemi per esempi WCF.

Per eseguire l'esempio tra computer

  1. Copiare i file Setup.bat, Cleanup.bate ImportClientCert.bat nel computer del servizio.

  2. Creare una directory nel computer client per i file binari client.

  3. Copiare i file di programma client nella directory client nel computer client. Copiare anche i file Setup.bat, Cleanup.bate ImportServiceCert.bat nel client.

  4. Nel server eseguire setup.bat service. L'esecuzione di setup.bat con l'argomento service crea un certificato del servizio con il nome di dominio completo del computer ed esporta il certificato del servizio in un file denominato Service.cer.

  5. Modificare il service.exe.config del servizio in modo da riflettere il nuovo nome del certificato (nell'attributo findValue nel <serviceCertificate>) che corrisponde al nome di dominio completo del computer.

  6. Copiare il file Service.cer dalla directory del servizio alla directory client nel computer client.

  7. Nel client eseguire setup.bat client. L'esecuzione di setup.bat con l'argomento client crea un certificato client denominato client.com ed esporta il certificato client in un file denominato Client.cer.

  8. Nel file Client.exe.config sul computer client, modificare il valore dell'indirizzo dell'endpoint affinché corrisponda al nuovo indirizzo del servizio. A tale scopo, sostituire localhost con il nome di dominio completo del server. È inoltre necessario modificare il nome del certificato del servizio in modo che corrisponda al nome di dominio completo del computer del servizio (nell'attributo findValue nell'elemento defaultCertificate di serviceCertificate in clientCredentials).

  9. Copiare il file Client.cer dalla directory client alla directory del servizio nel server.

  10. Nel client eseguire ImportServiceCert.bat. Questo importa il certificato del servizio dal file Service.cer nell'archivio CurrentUser - TrustedPeople.

  11. Nel server eseguire ImportClientCert.bat, importa il certificato client dal file Client.cer nell'archivio LocalMachine - TrustedPeople.

  12. Sul computer di servizio, avviare Service.exe dal prompt dei comandi.

  13. Nel computer client avviare Client.exe dal prompt dei comandi. Se il client e il servizio non sono in grado di comunicare, vedere Suggerimenti per la risoluzione dei problemi degli esempi WCF.

Per eseguire la pulizia dopo l'esempio

  • Eseguire Cleanup.bat nella cartella samples dopo aver completato l'esecuzione dell'esempio.

    Nota

    Questo script non rimuove i certificati del servizio in un client durante l'esecuzione di questo esempio tra computer. Se hai eseguito esempi di Windows Communication Foundation (WCF) che utilizzano certificati tra diversi computer, assicurati di rimuovere i certificati del servizio che sono stati installati nell'archivio CurrentUser - TrustedPeople. A tale scopo, usare il comando seguente: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name> Ad esempio: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.

Requisiti

Questo esempio richiede l'installazione e l'esecuzione di MSMQ.

Dimostra

Il client crittografa il messaggio usando la chiave pubblica del servizio e firma il messaggio usando il proprio certificato. Il servizio che legge il messaggio dalla coda autentica il certificato client con il certificato nel suo archivio di persone attendibili di fiducia. Quindi decrittografa il messaggio e lo invia all'operazione del servizio.

Poiché il messaggio Windows Communication Foundation (WCF) viene trasportato come payload nel corpo del messaggio MSMQ, il corpo rimane crittografato nell'archivio MSMQ. In questo modo il messaggio viene protetto dalla divulgazione indesiderata del messaggio. Si noti che MSMQ stesso non è in grado di sapere se il messaggio che sta trasportando è crittografato.

L'esempio illustra come usare l'autenticazione reciproca a livello di messaggio con MSMQ. I certificati vengono scambiati fuori banda. Questo è sempre il caso dell'applicazione in coda perché il servizio e il client non devono essere operativi contemporaneamente.

Descrizione

Il codice del client e del servizio di esempio è identico a quello dell''associazione MSMQ transazionata esempio con una differenza. Il contratto dell'operazione viene annotato con il livello di protezione, che suggerisce che il messaggio deve essere firmato e crittografato.

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

Per assicurarsi che il messaggio sia protetto usando il token necessario per identificare il servizio e il client, il App.config contiene informazioni sulle credenziali.

La configurazione client specifica il certificato del servizio per autenticare il servizio. Usa l'archivio LocalMachine come archivio attendibile per basarsi sulla validità del servizio. Specifica inoltre il certificato client associato al messaggio per l'autenticazione del servizio del 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>

Si noti che la modalità di sicurezza è impostata su Message e ClientCredentialType è impostata su Certificato.

La configurazione del servizio include un comportamento del servizio che specifica le credenziali del servizio usate quando il client autentica il servizio. Il nome soggetto del certificato server viene specificato nell'attributo findValue nel <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'esempio illustra il controllo dell'autenticazione usando la configurazione e come ottenere l'identità del chiamante dal contesto di sicurezza, come illustrato nel codice di esempio seguente:

// 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);
    }
  //…
}

Quando viene eseguito, il codice del servizio visualizza l'identificazione client. Di seguito è riportato un output di esempio del codice del servizio:

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

Commenti

  • Creazione del certificato client.

    La riga seguente nel file batch crea il certificato client. Il nome client specificato viene usato nel nome soggetto del certificato creato. Il certificato è archiviato nell'archivio My alla posizione dell'archivio CurrentUser.

    echo ************
    echo making client cert
    echo ************
    makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
    
  • Installazione del certificato client nell'archivio certificati attendibile del server.

    La riga seguente nel file batch copia il certificato client nell'archivio TrustedPeople del server in modo che il server possa prendere le decisioni di attendibilità o senza attendibilità pertinenti. Affinché un certificato installato nell'archivio TrustedPeople sia considerato attendibile da un servizio Windows Communication Foundation (WCF), la modalità di convalida del certificato client deve essere impostata sul valore PeerOrChainTrust o PeerTrust. Vedere l'esempio di configurazione del servizio precedente per informazioni su come eseguire questa operazione usando un file di configurazione.

    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
    
  • Creazione del certificato del server.

    Le righe seguenti del file batch Setup.bat creano il certificato del server da usare:

    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 variabile %SERVER_NAME% specifica il nome del server. Il certificato viene archiviato nell'archivio LocalMachine. Se il file batch di installazione viene eseguito con un argomento di servizio (ad esempio setup.bat service), il %SERVER_NAME% contiene il nome di dominio completo del computer. In caso contrario, l'impostazione predefinita è localhost.

  • Installazione del certificato server nell'archivio certificati attendibile del client.

    La riga seguente copia il certificato del server nell'archivio persone attendibili del client. Questo passaggio è obbligatorio perché i certificati generati da Makecert.exe non sono considerati implicitamente attendibili dal sistema client. Se si dispone già di un certificato radicato in un certificato radice attendibile per il client, ad esempio un certificato rilasciato da Microsoft, questo passaggio di popolamento dell'archivio certificati del client con il certificato del server non è obbligatorio.

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

    Nota

    Se si utilizza un'edizione inglese non statunitense di Microsoft Windows, è necessario modificare il file Setup.bat e sostituire il nome dell'account "NT AUTHORITY\NETWORK SERVICE" con l'equivalente regionale.