spring-integration - Spring 集成中的 TLS 和客户端身份验证
问题描述
我正在我的应用程序中试验 TLS、双向 TLS 和主机验证,并且对集成组件的行为有些困惑。我正在使用TcpNetClientConnection
工厂和TcpNetServerConnectionFactory
. 我对这些组件如何在后台进行交互没有深入的了解,并希望确保我的身份验证按预期工作(或不工作)。
@Bean
public TcpNetClientConnectionFactory tcpClientConnectionFactory() {
TcpNetClientConnectionFactory factory =
new TcpNetClientConnectionFactory(upstreamHost, upstreamPort);
factory.setTcpSocketFactorySupport(tcpSslSocketFactorySupport);
factory.setTcpSocketSupport(new DefaultTcpSocketSupport(isHostVerificationEnabled));
return factory;
}
@Bean
TcpNetServerConnectionFactory testTcpServerConnectionFactory() {
TcpNetServerConnectionFactory factory = new TcpNetServerConnectionFactory(upstreamPort);
factory.setTcpSocketFactorySupport(tcpSslSocketFactorySupport);
factory.setTcpSocketSupport(new DefaultTcpSocketSupport(isHostVerificationEnabled));
return factory;
}
@Bean
public DefaultTcpNetSSLSocketFactorySupport tcpSslSocketFactorySupport() {
TcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport(keyStore, trustStore, keyStorePassword,
trustStorePassword);
return new DefaultTcpNetSSLSocketFactorySupport(sslContextSupport);
}
似乎创建 a 的唯一方法TcpSSLContextSupport
是将密钥库和信任库都传递给它。为什么需要密钥库?如果我的服务器不需要客户端身份验证,我不应该将密钥库传递给我的客户端连接工厂。客户端工厂应该只需要有一个信任库,来验证它正在与之交谈的服务器。
关于客户端身份验证,我的配置中的服务器连接工厂是否需要客户端身份验证?根据参考资料,为了启用客户端身份验证,我需要重写该postProcessServerSocket()
方法。但是,在将客户端的证书添加到服务器的信任库之前,我遇到了 SSL 读取异常。为什么这是必要的,因为我还没有启用客户端身份验证?
最后,如果客户端连接工厂在其密钥库中确实有一个私钥条目,它会在打开与服务器的连接时自动使用该密钥吗?或者仅当服务器要求客户端身份验证时?似乎我的客户端连接工厂正在使用它的私钥,即使我还没有设置任何东西来强制客户端身份验证。
解决方案
服务器默认不需要clientAuth;文档中有一个关于如何要求它的示例。
请参阅此测试用例。
如果我注释掉第 437 行的代码
server.setTcpSocketSupport(new DefaultTcpSocketSupport(false) {
@Override
public void postProcessServerSocket(ServerSocket serverSocket) {
// ((SSLServerSocket) serverSocket).setNeedClientAuth(true);
}
});
测试失败
java.lang.AssertionError:
Expecting code to raise a throwable.
at org.springframework.integration.ip.tcp.connection.SocketSupportTests.testNetClientAndServerSSLDifferentContexts(SocketSupportTests.java:414)
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> testNetClientAndServerSSLDifferentContexts(true));
是的,默认实现需要一个密钥库,但是当不需要客户端身份验证时,它可以是空的或不包含客户端密钥的。我们可能应该放松一下;随时打开一个 GitHub 问题来请求它。和/或者你可以简单地提供你自己的实现。
在测试用例(预计会失败)中,我们使用不包含客户端证书的 keyStore。
TcpSSLContextSupport clientSslContextSupport = new DefaultTcpSSLContextSupport(
badClient ? "server.ks" : "client.ks",
"client.truststore.ks", "secret", "secret");
请注意,服务器套接字也有setWantsClientAuth
- 也许默认值true
可以解释您观察到的内容(如果您在客户端提供证书则失败)。我还没有测试过;尝试将其设置为 false。
推荐阅读
- arrays - Ruby 数组数组,根据数组中的唯一键将它们合并为一个数组
- c++ - 使用类外的函数
- python-3.x - 在 python 3 中,如何正确地将变量返回给函数?
- python - 熊猫合并具有相同ID的记录
- winapi - 如何在所选项目上设置组合框的背景颜色?
- duplicates - 如何在重复记录查询中选择特定记录
- playframework - 在 Couchbase 中实现 ACID(类似)转换
- postgresql - 如何使用数据工厂管道中 parquet 文件中的 ID 查询 Postgresql
- reactjs - Next js中组件的条件渲染
- javascript - 如何在该页面上执行功能之前使用异步 javascript 等待页面加载