Advanced Techniques
This section covers advanced techniques that you may find to be helpful in certain situations.
Strategy Interfaces
In many cases, the configuration described earlier is all that is needed to enable secure communication over TCP/IP. However, Spring Integration provides a number of strategy interfaces to allow customization and modification of socket factories and sockets:
-
TcpSSLContextSupport
-
TcpSocketFactorySupport
-
TcpSocketSupport
-
TcpNetConnectionSupport
-
TcpNioConnectionSupport
The TcpSSLContextSupport
Strategy Interface
The following listing shows the TcpSSLContextSupport
strategy interface:
public interface TcpSSLContextSupport {
SSLContext getSSLContext() throws Exception;
}
Implementations of the TcpSSLContextSupport
interface are responsible for creating an SSLContext
object.
The implementation provided by the framework is the DefaultTcpSSLContextSupport
, described earlier.
If you require different behavior, implement this interface and provide the connection factory with a reference to a bean of your class' implementation.
The TcpSocketFactorySupport
Strategy Interface
The following listing shows the definition of the TcpSocketFactorySupport
strategy interface:
public interface TcpSocketFactorySupport {
ServerSocketFactory getServerSocketFactory();
SocketFactory getSocketFactory();
}
Implementations of this interface are responsible for obtaining references to ServerSocketFactory
and SocketFactory
.
Two implementations are provided.
The first is DefaultTcpNetSocketFactorySupport
for non-SSL sockets (when no ssl-context-support
attribute is defined).
This uses the JDK’s default factories.
The second implementation is DefaultTcpNetSSLSocketFactorySupport
.
By default, this is used when an ssl-context-support
attribute is defined.
It uses the SSLContext
created by that bean to create the socket factories.
This interface applies only if using-nio is false .
NIO does not use socket factories.
|
The TcpSocketSupport
Strategy Interface
The following listing shows the definition of the TcpSocketSupport
strategy interface:
public interface TcpSocketSupport {
void postProcessServerSocket(ServerSocket serverSocket);
void postProcessSocket(Socket socket);
}
Implementations of this interface can modify sockets after they are created and after all configured attributes have been applied but before the sockets are used.
This applies whether you use NIO or not.
For example, you could use an implementation of this interface to modify the supported cipher suites on an SSL socket, or you could add a listener that gets notified after SSL handshaking is complete.
The sole implementation provided by the framework is the DefaultTcpSocketSupport
, which does not modify the sockets in any way.
To supply your own implementation of TcpSocketFactorySupport
or TcpSocketSupport
, provide the connection factory with references to beans of your custom type by setting the socket-factory-support
and socket-support
attributes, respectively.
The TcpNetConnectionSupport
Strategy Interface
The following listing shows the definition of the TcpNetConnectionSupport
strategy interface:
public interface TcpNetConnectionSupport {
TcpNetConnection createNewConnection(Socket socket,
boolean server, boolean lookupHost,
ApplicationEventPublisher applicationEventPublisher,
String connectionFactoryName) throws Exception;
}
This interface is invoked to create objects of type TcpNetConnection
(or its subclasses).
The framework provides a single implementation (DefaultTcpNetConnectionSupport
), which, by default, creates simple TcpNetConnection
objects.
It has two properties: pushbackCapable
and pushbackBufferSize
.
When push back is enabled, the implementation returns a subclass that wraps the connection’s InputStream
in a PushbackInputStream
.
Aligned with the PushbackInputStream
default, the buffer size defaults to 1.
This lets deserializers “unread” (push back) bytes into the stream.
The following trivial example shows how it might be used in a delegating deserializer that “peeks” at the first byte to determine which deserializer to invoke:
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);
}
}
}
The TcpNioConnectionSupport
Strategy Interface
The following listing shows the definition of the TcpNioConnectionSupport
strategy interface:
public interface TcpNioConnectionSupport {
TcpNioConnection createNewConnection(SocketChannel socketChannel,
boolean server, boolean lookupHost,
ApplicationEventPublisher applicationEventPublisher,
String connectionFactoryName) throws Exception;
}
This interface is invoked to create TcpNioConnection
objects (or objects from subclasses).
Spring Integration provides two implementations: DefaultTcpNioSSLConnectionSupport
and DefaultTcpNioConnectionSupport
.
Which one is used depends on whether SSL is in use.
A common use case is to subclass DefaultTcpNioSSLConnectionSupport
and override postProcessSSLEngine
.
See the SSL client authentication example.
As with the DefaultTcpNetConnectionSupport
, these implementations also support push back.
Example: Enabling SSL Client Authentication
To enable client certificate authentication when you use SSL, the technique depends on whether you use NIO.
When you do not NIO , provide a custom TcpSocketSupport
implementation to post-process the server socket:
serverFactory.setTcpSocketSupport(new DefaultTcpSocketSupport() {
@Override
public void postProcessServerSocket(ServerSocket serverSocket) {
((SSLServerSocket) serverSocket).setNeedClientAuth(true);
}
});
(When you use XML configuration, provide a reference to your bean by setting the socket-support
attribute).
When you use NIO, provide a custom TcpNioSslConnectionSupport
implementation to post-process the SSLEngine
, as the following example shows:
@Bean
public DefaultTcpNioSSLConnectionSupport tcpNioConnectionSupport() {
return new DefaultTcpNioSSLConnectionSupport(serverSslContextSupport) {
@Override
protected void postProcessSSLEngine(SSLEngine sslEngine) {
sslEngine.setNeedClientAuth(true);
}
}
}
@Bean
public TcpNioServerConnectionFactory server() {
...
serverFactory.setTcpNioConnectionSupport(tcpNioConnectionSupport());
...
}
(When you use XML configuration, since version 4.3.7, provide a reference to your bean by setting the nio-connection-support
attribute).