Schützen der Dienstremotingkommunikation in einem C#-DienstSecure service remoting communications in a C# service

Sicherheit ist einer der wichtigsten Aspekte der Kommunikation.Security is one of the most important aspects of communication. Das Reliable Services-Anwendungsframework stellt einige fertige Kommunikationsstapel und Tools bereit, die Sie verwenden können, um die Sicherheit zu verbessern.The Reliable Services application framework provides a few prebuilt communication stacks and tools that you can use to improve security. In diesem Artikel erfahren Sie, wie Sie die Sicherheit bei Verwendung von Dienstremoting in einem C#-Dienst verbessern können.This article discusses how to improve security when you're using service remoting in a C# service. Der Artikel erläutert anhand eines Beispiels, wie das Remoting für in C# geschriebene Reliable Services eingerichtet wird.It builds on an existing example that explains how to set up remoting for reliable services written in C#.

Gehen Sie wie folgt vor, um zum Schutz eines Diensts beizutragen, wenn Sie Dienstremoting mit C#-Diensten verwenden:To help secure a service when you're using service remoting with C# services, follow these steps:

  1. Erstellen Sie eine Schnittstelle, IHelloWorldStateful, die definiert, welche Methoden für einen Remoteprozeduraufruf Ihres Diensts verfügbar sind.Create an interface, IHelloWorldStateful, that defines the methods that will be available for a remote procedure call on your service. Ihr Dienst verwendet FabricTransportServiceRemotingListener, der im Namespace Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime deklariert wird.Your service will use FabricTransportServiceRemotingListener, which is declared in the Microsoft.ServiceFabric.Services.Remoting.FabricTransport.Runtime namespace. Dies ist eine ICommunicationListener -Implementierung, die Remotingfunktionen bereitstellt.This is an ICommunicationListener implementation that provides remoting capabilities.

    public interface IHelloWorldStateful : IService
    {
        Task<string> GetHelloWorld();
    }
    
    internal class HelloWorldStateful : StatefulService, IHelloWorldStateful
    {
        protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
        {
            return new[]{
                    new ServiceReplicaListener(
                        (context) => new FabricTransportServiceRemotingListener(context,this))};
        }
    
        public Task<string> GetHelloWorld()
        {
            return Task.FromResult("Hello World!");
        }
    }
    
  2. Fügen Sie Listenereinstellungen und Sicherheitsanmeldeinformationen hinzu.Add listener settings and security credentials.

    Stellen Sie sicher, dass das Zertifikat, das Sie zum Schutz Ihrer Dienstkommunikation verwenden möchten, auf allen Knoten im Cluster installiert ist.Make sure the certificate that you want to use to help secure your service communication is installed on all the nodes in the cluster.

    Hinweis

    Auf Linux-Knoten muss das Zertifikat in Form von Dateien im PEM-Format im Verzeichnis /var/lib/sfcerts vorgelegt werden.On Linux nodes, the certificate must be present as PEM-formatted files in the /var/lib/sfcerts directory. Weitere Informationen finden Sie unter Speicherort und Format von X.509-Zertifikaten auf Linux-Knoten.To learn more, see Location and format of X.509 certificates on Linux nodes.

    Es gibt zwei Möglichkeiten, wie Sie Listenereinstellungen und Sicherheitsanmeldeinformationen bereitstellen können:There are two ways that you can provide listener settings and security credentials:

    1. Direkte Bereitstellung im Dienstcode:Provide them directly in the service code:

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          FabricTransportRemotingListenerSettings  listenerSettings = new FabricTransportRemotingListenerSettings
          {
              MaxMessageSize = 10000000,
              SecurityCredentials = GetSecurityCredentials()
          };
          return new[]
          {
              new ServiceReplicaListener(
                  (context) => new FabricTransportServiceRemotingListener(context,this,listenerSettings))
          };
      }
      
      private static SecurityCredentials GetSecurityCredentials()
      {
          // Provide certificate details.
          var x509Credentials = new X509Credentials
          {
              FindType = X509FindType.FindByThumbprint,
              FindValue = "4FEF3950642138446CC364A396E1E881DB76B48C",
              StoreLocation = StoreLocation.LocalMachine,
              StoreName = "My",
              ProtectionLevel = ProtectionLevel.EncryptAndSign
          };
          x509Credentials.RemoteCommonNames.Add("ServiceFabric-Test-Cert");
          x509Credentials.RemoteCertThumbprints.Add("9FEF3950642138446CC364A396E1E881DB76B483");
          return x509Credentials;
      }
      
    2. Bereitstellung mithilfe eines Konfigurationspakets:Provide them by using a config package:

      Fügen Sie in der Datei „settings.xml“ einen Abschnitt namens TransportSettings hinzu.Add a named TransportSettings section in the settings.xml file.

      <Section Name="HelloWorldStatefulTransportSettings">
          <Parameter Name="MaxMessageSize" Value="10000000" />
          <Parameter Name="SecurityCredentialsType" Value="X509" />
          <Parameter Name="CertificateFindType" Value="FindByThumbprint" />
          <Parameter Name="CertificateFindValue" Value="4FEF3950642138446CC364A396E1E881DB76B48C" />
          <Parameter Name="CertificateRemoteThumbprints" Value="9FEF3950642138446CC364A396E1E881DB76B483" />
          <Parameter Name="CertificateStoreLocation" Value="LocalMachine" />
          <Parameter Name="CertificateStoreName" Value="My" />
          <Parameter Name="CertificateProtectionLevel" Value="EncryptAndSign" />
          <Parameter Name="CertificateRemoteCommonNames" Value="ServiceFabric-Test-Cert" />
      </Section>
      

      In diesem Fall sieht die CreateServiceReplicaListeners -Methode wie folgt aus:In this case, the CreateServiceReplicaListeners method will look like this:

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new[]
          {
              new ServiceReplicaListener(
                  (context) => new FabricTransportServiceRemotingListener(
                      context,this,FabricTransportRemotingListenerSettings .LoadFrom("HelloWorldStatefulTransportSettings")))
          };
      }
      

      Wenn Sie in der Datei „settings.xml“ den Abschnitt TransportSettings hinzufügen, lädt FabricTransportRemotingListenerSettings standardmäßig alle Einstellungen aus diesem Abschnitt.If you add a TransportSettings section in the settings.xml file , FabricTransportRemotingListenerSettings will load all the settings from this section by default.

      <!--"TransportSettings" section .-->
      <Section Name="TransportSettings">
          ...
      </Section>
      

      In diesem Fall sieht die CreateServiceReplicaListeners -Methode wie folgt aus:In this case, the CreateServiceReplicaListeners method will look like this:

      protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners()
      {
          return new[]
          {
              return new[]{
                      new ServiceReplicaListener(
                          (context) => new FabricTransportServiceRemotingListener(context,this))};
          };
      }
      
  3. Wenn Sie Methoden für einen gesicherten Dienst mit dem Remotingstapel aufrufen, statt mit der Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy-Klasse einen Dienstproxy zu erstellen, verwenden Sie Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory.When you call methods on a secured service by using the remoting stack, instead of using the Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy class to create a service proxy, use Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxyFactory. Übergeben Sie FabricTransportRemotingSettings, worin SecurityCredentials enthalten ist.Pass in FabricTransportRemotingSettings, which contains SecurityCredentials.

    
    var x509Credentials = new X509Credentials
    {
        FindType = X509FindType.FindByThumbprint,
        FindValue = "9FEF3950642138446CC364A396E1E881DB76B483",
        StoreLocation = StoreLocation.LocalMachine,
        StoreName = "My",
        ProtectionLevel = ProtectionLevel.EncryptAndSign
    };
    x509Credentials.RemoteCommonNames.Add("ServiceFabric-Test-Cert");
    x509Credentials.RemoteCertThumbprints.Add("4FEF3950642138446CC364A396E1E881DB76B48C");
    
    FabricTransportRemotingSettings transportSettings = new FabricTransportRemotingSettings
    {
        SecurityCredentials = x509Credentials,
    };
    
    ServiceProxyFactory serviceProxyFactory = new ServiceProxyFactory(
        (c) => new FabricTransportServiceRemotingClientFactory(transportSettings));
    
    IHelloWorldStateful client = serviceProxyFactory.CreateServiceProxy<IHelloWorldStateful>(
        new Uri("fabric:/MyApplication/MyHelloWorldService"));
    
    string message = await client.GetHelloWorld();
    
    

    Wenn der Clientcode als Teil eines Diensts ausgeführt wird, können Sie das FabricTransportRemotingSettings -Element aus der Datei „settings.xml“ laden.If the client code is running as part of a service, you can load FabricTransportRemotingSettings from the settings.xml file. Erstellen Sie den Abschnitt „HelloWorldClientTransportSettings“, der dem obigen Dienstcode ähnelt.Create a HelloWorldClientTransportSettings section that is similar to the service code, as shown earlier. Nehmen Sie die folgenden Änderungen am Clientcode vor:Make the following changes to the client code:

    ServiceProxyFactory serviceProxyFactory = new ServiceProxyFactory(
        (c) => new FabricTransportServiceRemotingClientFactory(FabricTransportRemotingSettings.LoadFrom("HelloWorldClientTransportSettings")));
    
    IHelloWorldStateful client = serviceProxyFactory.CreateServiceProxy<IHelloWorldStateful>(
        new Uri("fabric:/MyApplication/MyHelloWorldService"));
    
    string message = await client.GetHelloWorld();
    
    

    Wenn der Client nicht als Teil eines Diensts ausgeführt wird, können Sie die Datei „client_name.settings.xml“ an dem gleichen Speicherort erstellen, an dem sich auch die Datei „client_name.exe“ befindet.If the client is not running as part of a service, you can create a client_name.settings.xml file in the same location where the client_name.exe is. Erstellen Sie dann einen Abschnitt „TransportSettings“ in dieser Datei.Then create a TransportSettings section in that file.

    Ähnlich wie beim Dienst gilt Folgendes: Wenn Sie in der Datei „client settings.xml/client_name.settings.xml“ den Abschnitt TransportSettings hinzufügen, lädt FabricTransportRemotingSettings standardmäßig alle Einstellungen aus diesem Abschnitt.Similar to the service, if you add a TransportSettings section in client settings.xml/client_name.settings.xml, FabricTransportRemotingSettings loads all the settings from this section by default.

    In diesem Fall wird der frühere Code noch weiter vereinfacht:In that case, the earlier code is even further simplified:

    
    IHelloWorldStateful client = ServiceProxy.Create<IHelloWorldStateful>(
                 new Uri("fabric:/MyApplication/MyHelloWorldService"));
    
    string message = await client.GetHelloWorld();
    
    

Lesen Sie als Nächstes den Artikel Web-API mit OWIN in Reliable Services.As a next step, read Web API with OWIN in Reliable Services.