gpt4 book ai didi

java - Spring Boot SSL TCPClient ~ StompBrokerRelayMessageHandler ~ ActiveMQ ~ Undertow

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:38:15 26 4
gpt4 key购买 nike

我正在尝试基于 Spring Websocket Demo 构建一个 websocket 消息传递应用程序运行 ActiveMQ作为 Undertow 的 STOMP 消息代理.该应用程序在不安全的连接上运行良好。但是,我在配置 STOMP Broker Relay 时遇到困难使用 SSL 连接转发。

如 Spring WebSocket 文档中所述...

The "STOMP broker relay" in the above configuration is a Spring MessageHandler that handles messages by forwarding them to an external message broker. To do so it establishes TCP connections to the broker, forwards all messages to it, and then forwards all messages received from the broker to clients through their WebSocket sessions. Essentially it acts as a "relay" that forwards messages in both directions.

此外,文档说明了对 reactor-net 的依赖性我有...

Please add a dependency on org.projectreactor:reactor-net for TCP connection management.

问题是我当前的实现没有初始化 NettyTCPClient通过 SSL,因此 ActiveMQ 连接失败并出现 SSLException。


[r.i.n.i.n.t.NettyTcpClient:307] » CONNECTED: 
[id: 0xcfef39e9, /127.0.0.1:17779 => localhost/127.0.0.1:8442]
...
[o.a.a.b.TransportConnection.Transport:245] »
Transport Connection to: tcp://127.0.0.1:17779 failed:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
...

因此,我尝试研究 Project Reactor Docs为连接设置 SSL 选项,但我没有成功。

此时我找到了 StompBrokerRelayMessageHandler初始化 NettyTCPClient默认在 Reactor2TcpClient然而,它似乎不可配置。

如有帮助,我们将不胜感激。

中南合作商会


app.props

spring.activemq.in-memory=true
spring.activemq.pooled=false
spring.activemq.broker-url=stomp+ssl://localhost:8442
server.port=8443
server.ssl.enabled=true
server.ssl.protocol=tls
server.ssl.key-alias=undertow
server.ssl.key-store=classpath:undertow.jks
server.ssl.key-store-password=xxx
server.ssl.trust-store=classpath:undertow_certs.jks
server.ssl.trust-store-password=xxx

WebSocketConfig

//... 
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

private static final Logger log = LoggerFactory.getLogger(WebSocketConfig.class);

private final static String KEYSTORE = "/activemq.jks";
private final static String KEYSTORE_PASS = "xxx";
private final static String KEYSTORE_TYPE = "JKS";
private final static String TRUSTSTORE = "/activemq_certs.jks";
private final static String TRUSTSTORE_PASS = "xxx";

private static String getBindLocation() {
return "stomp+ssl://localhost:8442?transport.needClientAuth=false";
}

@Bean(initMethod = "start", destroyMethod = "stop")
public SslBrokerService activeMQBroker() throws Exception {

final SslBrokerService service = new SslBrokerService();
service.setPersistent(false);

KeyManager[] km = SecurityManager.getKeyManager();
TrustManager[] tm = SecurityManager.getTrustManager();

service.addSslConnector(getBindLocation(), km, tm, null);
final ActiveMQTopic topic = new ActiveMQTopic("jms.topic.test");
service.setDestinations(new ActiveMQDestination[]{topic});

return service;
}


@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableStompBrokerRelay("/topic").setRelayHost("localhost").setRelayPort(8442);
config.setApplicationDestinationPrefixes("/app");
}

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/welcome").withSockJS();
registry.addEndpoint("/test").withSockJS();
}

private static class SecurityManager {
//elided...
}

}

SOLVED Per Rossens Advice. Here's the implementation details for anyone interested.


WebSocketConfig

@Configuration
public class WebSocketConfig extends DelegatingWebSocketMessageBrokerConfiguration {
...
@Bean
public AbstractBrokerMessageHandler stompBrokerRelayMessageHandler() {
StompBrokerRelayMessageHandler handler = (StompBrokerRelayMessageHandler) super.stompBrokerRelayMessageHandler();
ConfigurationReader reader = new StompClientDispatcherConfigReader();
Environment environment = new Environment(reader).assignErrorJournal();
TcpOperations<byte[]> client = new Reactor2TcpClient<>(new StompTcpClientSpecFactory(environment,"localhost", 8443));
handler.setTcpClient(client);
return handler;
}
}

StompTCPClientSpecFactory

private static class StompTcpClientSpecFactory
implements NetStreams.TcpClientFactory<Message<byte[]>, Message<byte[]>> {

private static final Logger log = LoggerFactory.getLogger(StompTcpClientSpecFactory.class);

private final String host;
private final int port;
private final String KEYSTORE = "src/main/resources/tcpclient.jks";
private final String KEYSTORE_PASS = "xxx";
private final String KEYSTORE_TYPE = "JKS";
private final String TRUSTSTORE = "/src/main/resources/tcpclient_certs.jks";
private final String TRUSTSTORE_PASS = "xxx";
private final String TRUSTSTORE_TYPE = "JKS";
private final Environment environment;

private final SecurityManager tcpManager = new SecurityManager
.SSLBuilder(KEYSTORE, KEYSTORE_PASS)
.keyStoreType(KEYSTORE_TYPE)
.trustStore(TRUSTSTORE, TRUSTSTORE_PASS)
.trustStoreType(TRUSTSTORE_TYPE)
.build();

public StompTcpClientSpecFactory(Environment environment, String host, int port) {
this.environment = environment;
this.host = host;
this.port = port;
}

@Override
public Spec.TcpClientSpec<Message<byte[]>, Message<byte[]>> apply(
Spec.TcpClientSpec<Message<byte[]>, Message<byte[]>> tcpClientSpec) {

return tcpClientSpec
.ssl(new SslOptions()
.sslProtocol("TLS")
.keystoreFile(tcpManager.getKeyStore())
.keystorePasswd(tcpManager.getKeyStorePass())
.trustManagers(tcpManager::getTrustManager)
.trustManagerPasswd(tcpManager.getTrustStorePass()))
.codec(new Reactor2StompCodec(new StompEncoder(), new StompDecoder()))
.env(this.environment)
.dispatcher(this.environment.getCachedDispatchers("StompClient").get())
.connect(this.host, this.port);
}
}

最佳答案

StompBrokerRelayMessageHandler 有一个可以设置的 tcpClient 属性。但是,我们似乎没有通过 WebSocketMessageBrokerConfigurer 设置公开它。

您可以删除 @EnableWebSocketMessageBroker 并改为扩展 DelegatingWebSocketMessageBrokerConfiguration。它实际上是相同的,但您现在直接从提供所有 bean 的配置类进行扩展。

这允许您覆盖 stompBrokerRelayMessageHandler() bean 并直接设置其 TcpClient 属性。只需确保重写方法用 @Bean 标记即可。

关于java - Spring Boot SSL TCPClient ~ StompBrokerRelayMessageHandler ~ ActiveMQ ~ Undertow,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34334629/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com