高级技术
本节介绍在某些情况下可能会有用的高级技术。
策略接口
在许多情况下,前面描述的配置就是通过 TCP/IP 启用安全通信所需的全部内容。 但是, Spring 集成提供了许多策略接口,以允许自定义和修改套接字工厂和套接字:
- 
TcpSSLContextSupport
- 
TcpSocketFactorySupport
- 
TcpSocketSupport
- 
TcpNetConnectionSupport
- 
TcpNioConnectionSupport
这TcpSSLContextSupport策略界面
下面的清单显示了TcpSSLContextSupport策略界面:
public interface TcpSSLContextSupport {
    SSLContext getSSLContext() throws Exception;
}的TcpSSLContextSupportinterface 负责创建一个SSLContext对象。
框架提供的实现是DefaultTcpSSLContextSupport,如前所述。
如果需要不同的行为,请实现此接口,并为连接工厂提供对类实现的 bean 的引用。
这TcpSocketFactorySupport策略界面
下面的清单显示了TcpSocketFactorySupport策略界面:
public interface TcpSocketFactorySupport {
    ServerSocketFactory getServerSocketFactory();
    SocketFactory getSocketFactory();
}此接口的实现负责获取对ServerSocketFactory和SocketFactory.
提供了两种实现。
首先是DefaultTcpNetSocketFactorySupport对于非 SSL 套接字(当没有ssl-context-support属性)。
这将使用 JDK 的默认工厂。
第二个实现是DefaultTcpNetSSLSocketFactorySupport.
默认情况下,当ssl-context-support属性。
它使用SSLContext由该 bean 创建以创建套接字工厂。
| 此接口仅在以下情况下适用 using-nio是false.
NIO 不使用 socket 工厂。 | 
这TcpSocketSupport策略界面
下面的清单显示了TcpSocketSupport策略界面:
public interface TcpSocketSupport {
    void postProcessServerSocket(ServerSocket serverSocket);
    void postProcessSocket(Socket socket);
}此接口的实现可以在创建套接字之后以及应用所有配置的属性之后但在使用套接字之前修改套接字。
无论您是否使用 NIO,这都适用。
例如,您可以使用此接口的实现来修改 SSL 套接字上支持的密码套件,也可以添加在 SSL 握手完成后收到通知的侦听器。
框架提供的唯一实现是DefaultTcpSocketSupport,它不会以任何方式修改套接字。
要提供您自己的TcpSocketFactorySupport或TcpSocketSupport中,通过设置socket-factory-support和socket-support属性。
这TcpNetConnectionSupport策略界面
下面的清单显示了TcpNetConnectionSupport策略界面:
public interface TcpNetConnectionSupport {
    TcpNetConnection createNewConnection(Socket socket,
            boolean server, boolean lookupHost,
            ApplicationEventPublisher applicationEventPublisher,
            String connectionFactoryName) throws Exception;
}调用此接口以创建TcpNetConnection(或其子类)。
该框架提供了一个实现 (DefaultTcpNetConnectionSupport),默认情况下,它会创建简单的TcpNetConnection对象。
它有两个属性:pushbackCapable和pushbackBufferSize.
启用后推后,实现返回一个子类,该子类包装了连接的InputStream在PushbackInputStream.
与PushbackInputStreamdefault,缓冲区大小默认为 1。
这允许反序列化器将 “unread” (push back) 字节放入流中。
下面的简单示例显示了如何在委托 deserializer 中使用它,该 deserializer “peeks” 第一个字节以确定要调用哪个 deserializer:
public class CompositeDeserializer implements Deserializer<byte[]> {
    private final ByteArrayStxEtxSerializer stxEtx = new ByteArrayStxEtxSerializer();
    private final ByteArrayCrLfSerializer crlf = new ByteArrayCrLfSerializer();
    @Override
    public byte[] deserialize(InputStream inputStream) throws IOException {
        PushbackInputStream pbis = (PushbackInputStream) inputStream;
        int first = pbis.read();
        if (first < 0) {
            throw new SoftEndOfStreamException();
        }
        pbis.unread(first);
        if (first == ByteArrayStxEtxSerializer.STX) {
            this.receivedStxEtx = true;
            return this.stxEtx.deserialize(pbis);
        }
        else {
            this.receivedCrLf = true;
            return this.crlf.deserialize(pbis);
        }
    }
}这TcpNioConnectionSupport策略界面
下面的清单显示了TcpNioConnectionSupport策略界面:
public interface TcpNioConnectionSupport {
    TcpNioConnection createNewConnection(SocketChannel socketChannel,
            boolean server, boolean lookupHost,
            ApplicationEventPublisher applicationEventPublisher,
            String connectionFactoryName) throws Exception;
}调用此接口以创建TcpNioConnection对象(或来自子类的对象)。
Spring 集成提供了两种实现:DefaultTcpNioSSLConnectionSupport和DefaultTcpNioConnectionSupport.
使用哪一个取决于是否正在使用 SSL。
一个常见的用例是子类化DefaultTcpNioSSLConnectionSupport并覆盖postProcessSSLEngine.
请参阅 SSL 客户端身份验证示例。
与DefaultTcpNetConnectionSupport,这些实现还支持 Push Back。
示例:启用 SSL 客户端身份验证
要在使用 SSL 时启用客户端证书身份验证,该技术取决于您是否使用 NIO。
当您没有 NIO 时,请提供自定义TcpSocketSupport实现对服务器套接字进行后处理:
serverFactory.setTcpSocketSupport(new DefaultTcpSocketSupport() {
    @Override
    public void postProcessServerSocket(ServerSocket serverSocket) {
        ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
    }
});(当您使用 XML 配置时,通过设置socket-support属性)。
当您使用 NIO 时,请提供自定义TcpNioSslConnectionSupportimplementation 对SSLEngine,如下例所示:
@Bean
public DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport() {
    return new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport) {
            @Override
            protected void postProcessSSLEngine(SSLEngine sslEngine) {
                sslEngine.setNeedClientAuth(true);
            }
    }
}
@Bean
public TcpNioServerConnectionFactory server() {
    ...
    serverFactory.setTcpNioConnectionSupport(tcpNioConnectionSupport());
    ...
}(当您使用 XML 配置时,从版本 4.3.7 开始,通过设置nio-connection-support属性)。