保护 Java 服务的服务远程处理通信Secure service remoting communications in a Java service
安全是通信最为重视的要素之一。Security is one of the most important aspects of communication. Reliable Services 应用程序框架提供了一些预先构建的通信堆栈和工具,可用来提高安全性。The Reliable Services application framework provides a few prebuilt communication stacks and tools that you can use to improve security. 本文介绍如何在 Java 服务中使用服务远程处理时提高安全性。This article discusses how to improve security when you're using service remoting in a Java service. 它基于现有的示例构建,该示例解释了如何为使用 Java 编写的可靠服务设置远程处理。It builds on an existing example that explains how to set up remoting for reliable services written in Java.
若要在 Java 服务中使用服务远程处理时帮助保护服务,请遵循以下步骤:To help secure a service when you're using service remoting with Java services, follow these steps:
创建接口
HelloWorldStateless
,用于定义可供服务的远程过程调用使用的方法。Create an interface,HelloWorldStateless
, that defines the methods that will be available for a remote procedure call on your service. 服务将使用microsoft.serviceFabric.services.remoting.fabricTransport.runtime
包中声明的FabricTransportServiceRemotingListener
。Your service will useFabricTransportServiceRemotingListener
, which is declared in themicrosoft.serviceFabric.services.remoting.fabricTransport.runtime
package. 这是可以提供远程处理功能的CommunicationListener
实现。This is anCommunicationListener
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!"); } }
添加侦听器设置和安全凭据。Add listener settings and security credentials.
确保要用来帮助保护服务通信的证书安装在群集中的所有节点上。Make sure the certificate that you want to use to help secure your service communication is installed on all the nodes in the cluster. 对于在 Linux 上运行的服务,证书必须以 PEM 格式的文件提供,要么是包含证书和私钥的
.pem
文件,要么是包含证书的.crt
文件和包含私钥的.key
文件。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. 有关详细信息,请参阅 Linux 节点上的 X.509 证书的位置和格式。To learn more, see Location and format of X.509 certificates on Linux nodes.有两种方式可用于提供侦听器设置和安全凭据:There are two ways that you can provide listener settings and security credentials:
使用配置包提供:Provide them by using a config package:
在 settings.xml 文件中添加名为
TransportSettings
的节。Add a namedTransportSettings
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>
在这种情况下,
createServiceInstanceListeners
方法如下所示:In this case, thecreateServiceInstanceListeners
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; }
如果将在 settings.xml 中添加
TransportSettings
节而不添加任何前缀,则FabricTransportListenerSettings
将按默认加载此节中的所有设置。If you add aTransportSettings
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>
在这种情况下,
CreateServiceInstanceListeners
方法如下所示:In this case, theCreateServiceInstanceListeners
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; }
在安全服务上使用远程堆栈(而不是使用
microsoft.serviceFabric.services.remoting.client.ServiceProxyBase
类)调用方法来创建服务代理时,请使用microsoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory
。When you call methods on a secured service by using the remoting stack, instead of using themicrosoft.serviceFabric.services.remoting.client.ServiceProxyBase
class to create a service proxy, usemicrosoft.serviceFabric.services.remoting.client.FabricServiceProxyFactory
.如果客户端代码正在作为服务的一部分运行,则可以从 settings.xml 文件中加载
FabricTransportSettings
。If the client code is running as part of a service, you can loadFabricTransportSettings
from the settings.xml file. 创建与服务代码类似的 TransportSettings 节,如上所示。Create a TransportSettings section that is similar to the service code, as shown earlier. 对客户端代码进行以下更改。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();