Schützen der Dienstremotingkommunikation in einem Java-DienstSecure service remoting communications in a Java 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 des Dienstremotings in einem Java-Dienst verbessern können.This article discusses how to improve security when you're using service remoting in a Java service. Der Artikel erläutert anhand eines Beispiels, wie das Remoting für in Java geschriebene Reliable Services eingerichtet wird.It builds on an existing example that explains how to set up remoting for reliable services written in Java.

Führen Sie die folgenden Schritte aus, um einen Dienst zu schützen, wenn Sie das Dienstremoting mit Java-Diensten verwenden:To help secure a service when you're using service remoting with Java services, follow these steps:

  1. Erstellen Sie eine Schnittstelle, HelloWorldStateless, die definiert, welche Methoden für einen Remoteprozeduraufruf Ihres Diensts verfügbar sind.Create an interface, HelloWorldStateless, that defines the methods that will be available for a remote procedure call on your service. Ihr Dienst verwendet FabricTransportServiceRemotingListener, der im Paket microsoft.serviceFabric.services.remoting.fabricTransport.runtime deklariert wird.Your service will use FabricTransportServiceRemotingListener, which is declared in the microsoft.serviceFabric.services.remoting.fabricTransport.runtime package. Dies ist eine CommunicationListener -Implementierung, die Remotingfunktionen bereitstellt.This is an CommunicationListener implementation that provides remoting capabilities.

    public interface HelloWorldStateless extends Service {
        CompletableFuture<String> getHelloWorld();
    }
    
    class HelloWorldStatelessImpl extends StatelessService implements HelloWorldStateless {
        @Override
        protected List<ServiceInstanceListener> createServiceInstanceListeners() {
            ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
            listeners.add(new ServiceInstanceListener((context) -> {
                return new FabricTransportServiceRemotingListener(context,this);
            }));
        return listeners;
        }
    
        public CompletableFuture<String> getHelloWorld() {
            return CompletableFuture.completedFuture("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. Bei unter Linux ausgeführten Diensten muss das Zertifikat als Datei im PEM-Format verfügbar sein: Entweder muss eine .pem-Datei vorhanden sein, die das Zertifikat und den privaten Schlüssel enthält, oder eine .crt-Datei mit dem Zertifikat und eine .key-Datei mit dem privaten Schlüssel.For services running on Linux, the certificate must be available as a PEM-formmatted file; either a .pem file that contains the certificate and private key or a .crt file that contains the certificate and a .key file that contains the private key. 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. 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 should always end with "TransportSettings".-->
      <!--Here we are using a prefix "HelloWorldStateless".-->
       <Section Name="HelloWorldStatelessTransportSettings">
           <Parameter Name="MaxMessageSize" Value="10000000" />
           <Parameter Name="SecurityCredentialsType" Value="X509_2" />
           <Parameter Name="CertificatePath" Value="/path/to/cert/BD1C71E248B8C6834C151174DECDBDC02DE1D954.crt" />
           <Parameter Name="CertificateProtectionLevel" Value="EncryptandSign" />
           <Parameter Name="CertificateRemoteThumbprints" Value="BD1C71E248B8C6834C151174DECDBDC02DE1D954" />
       </Section>
      
      

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

       protected List<ServiceInstanceListener> createServiceInstanceListeners() {
           ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
           listeners.add(new ServiceInstanceListener((context) -> {
               return new FabricTransportServiceRemotingListener(context,this, FabricTransportRemotingListenerSettings.loadFrom(HelloWorldStatelessTransportSettings));
           }));
           return listeners;
       }
      

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

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

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

      protected List<ServiceInstanceListener> createServiceInstanceListeners() {
          ArrayList<ServiceInstanceListener> listeners = new ArrayList<>();
          listeners.add(new ServiceInstanceListener((context) -> {
              return new FabricTransportServiceRemotingListener(context,this);
          }));
          return listeners;
      }
      
  3. Wenn Sie Methoden für einen gesicherten Dienst mit dem Remotingstapel aufrufen, statt mit der microsoft.serviceFabric.services.remoting.client.ServiceProxyBase-Klasse einen Dienstproxy zu erstellen, verwenden Sie microsoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory.When you call methods on a secured service by using the remoting stack, instead of using the microsoft.serviceFabric.services.remoting.client.ServiceProxyBase class to create a service proxy, use microsoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory.

    Wenn der Clientcode als Teil eines Diensts ausgeführt wird, können Sie das FabricTransportSettings -Element aus der Datei „settings.xml“ laden.If the client code is running as part of a service, you can load FabricTransportSettings from the settings.xml file. Erstellen Sie einen TransportSettings-Abschnitt, der dem obigen Dienstcode ähnelt.Create a TransportSettings 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:

    
    FabricServiceProxyFactory serviceProxyFactory = new FabricServiceProxyFactory(c -> {
            return new FabricTransportServiceRemotingClientFactory(FabricTransportRemotingSettings.loadFrom("TransportPrefixTransportSettings"), null, null, null, null);
        }, null)
    
    HelloWorldStateless client = serviceProxyFactory.createServiceProxy(HelloWorldStateless.class,
        new URI("fabric:/MyApplication/MyHelloWorldService"));
    
    CompletableFuture<String> message = client.getHelloWorld();