INT-4198: TCP: Add Hook to Customize SSLEngine

JIRA: https://jira.spring.io/browse/INT-4198

Enable setting properties like `needClientAuth` on the `SSLEngine` - when not using
NIO, this can be set on the server socket with a socket support implementation.

Add `nio-connection-support` to namespace.

Improved "Advanced Techniques" documentation, using this use case as an example.

Fail fast with NIO when SSL handshaking fails.

Polishing - PR Comments

More Polishing

* Final polishing
- fix several typos in log messages
- clean up `TcpConnectionFactoryFactoryBean` JavaDocs from redundant imports
- remove redundant `InitializationBean` functionality from the `DefaultTcpNetSSLSocketFactorySupport` as well
This commit is contained in:
Gary Russell
2016-12-28 14:58:16 -05:00
committed by Artem Bilan
parent bdab0aa1d3
commit a0f0b6ab64
14 changed files with 297 additions and 108 deletions

View File

@@ -886,17 +886,20 @@ After establishing the key stores, the next step is to indicate their locations
type="client"
host="localhost"
port="1234"
ssl-context-support="sslContextSupport"
ssl-context-support="sslContextSupport" />
----
The `DefaulTcpSSLContextSupport` class also has an optional 'protocol' property, which can be 'SSL' or 'TLS' (default).
The `DefaulTcpSSLContextSupport` class also has an optional `protocol` property, which can be `SSL` or `TLS` (default).
The keystore file names (first two constructor arguments) use the Spring `Resource` abstraction; by default the files will be located on the classpath, but this can be overridden by using the `file:` prefix, to find the files on the filesystem instead.
Starting with _version 4.3.6_, when using NIO, you can specify an `ssl-handshake-timeout` (seconds) on the connection factory.
This timeout (default 30) is used during SSL handshake when waiting for data; if the timeout is exceeded, the process is aborted and the socket closed.
==== Advanced Techniques
[[advanced-techniques]]
=== Advanced Techniques
==== Strategy Interfaces
In many cases, the configuration described above is all that is needed to enable secure communication over TCP/IP.
However, a number of strategy interfaces are provided to allow customization and modification of socket factories and sockets.
@@ -904,18 +907,19 @@ However, a number of strategy interfaces are provided to allow customization and
* `TcpSSLContextSupport`
* `TcpSocketFactorySupport`
* `TcpSocketSupport`
* `TcpNioConnectionSupport`
[source,java]
----
public interface TcpSSLContextSupport {
SSLContext getSSLContext() throws Exception;
SSLContext getSSLContext() throws Exception;
}
----
Implementations of this interface are responsible for creating an SSLContext.
The sole implementation provided by the framework is the `DefaultTcpSSLContextSupport` described above.
The implementation provided by the framework is the `DefaultTcpSSLContextSupport` described above.
If you require different behavior, implement this interface and provide the connection factory with a reference to a bean of your class' implementation.
[source,java]
@@ -931,8 +935,8 @@ public interface TcpSocketFactorySupport {
----
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 simply uses the JDK's default factories.
The second implementation is `DefaultTcpNetSSLSocketFactorySupport`; this is used, by default, when an 'ssl-context-support' attribute is defined; it uses the `SSLContext` created by that bean to create the socket factories.
Two implementations are provided; the first is `DefaultTcpNetSocketFactorySupport` for non-SSL sockets (when no `ssl-context-support` attribute is defined); this simply uses the JDK's default factories.
The second implementation is `DefaultTcpNetSSLSocketFactorySupport`; this is used, by default, when an `ssl-context-support` attribute is defined; it uses the `SSLContext` created by that bean to create the socket factories.
NOTE: This interface only applies if `using-nio` is "false"; socket factories are not used by NIO.
@@ -944,7 +948,7 @@ public interface TcpSocketSupport {
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.
@@ -954,6 +958,68 @@ The sole implementation provided by the framework is the `DefaultTcpSocketSuppor
To supply your own implementation of `TcpSocketFactorySupport` or `TcpSocketSupport`, provide the connection factory with references to beans of your custom type using the `socket-factory-support` and `socket-support` attributes, respectively.
[source, java]
----
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 subclasses).
Two implementations are provided `DefaultTcpNioSSLConnectionSupport` and `DefaultTcpNioConnectionSupport` which are used depending on whether SSL is in use or not.
A common use case would be to subclass `DefaultTcpNioSSLConnectionSupport` and override `postProcessSSLEngine`; see the example below.
==== Example: Enabling SSL Client Authentication
To enable client certificate authentication when using SSL, the technique depends on whether NIO is in use or not.
When NIO is not being used, provide a custom `TcpSocketSupport` implementation to post-process the server socket:
[source, java]
----
serverFactory.setTcpSocketSupport(new DefaultTcpSocketSupport() {
@Override
public void postProcessServerSocket(ServerSocket serverSocket) {
((SSLServerSocket) serverSocket).setNeedClientAuth(true);
}
});
----
(When using XML configuration, provide a reference to your bean using the `socket-support` attribute).
When using NIO, provide a custom `TcpNioSslConnectionSupport` implementation to post-process the `SSLEngine`.
[source, java]
----
@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 using XML configuration, since _version 4.3.7_, provide a reference to your bean using the `nio-connection-support` attribute).
[[ip-endpoint-reference]]
=== IP Configuration Attributes
@@ -1116,6 +1182,11 @@ Defaults to true.
| Y
|
| See <<ssl-tls>>
| nio-connection-support
| Y
| Y
|
| See <<advanced-techniques>>
| read-delay
| Y
| Y