- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试基于 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/
最近我的 Undertow 应用程序触发 Cloud Run 报告以下内容: Container Sandbox Limitation: Unsupported syscall setsockopt(
要使用 undertow 作为代理服务器来跟踪所有流量(调试目的所需),我目前使用的代码片段如下: Undertow.builder() .addHttpListener(8080, null
当我访问我的网络服务器时,我使用 ResourceHandler 来提供 javascript 文件。现在的问题是,我想提供完全相同的 JavaScript,但在我的 url 中接受/{id},这样当
我正在使用 undertow 开发一个 web 应用程序,并且对 java 相当陌生。运行 ServeletEngine.java 时出现错误。我检查了其他相关帖子,但他们没有解决我的疑问。请帮我。
有没有关于undertow.routing模板格式的文档?我想像这样设置处理程序: / or /index.html -> Use handler 1 Anything else -> Use han
本文整理了Java中io.undertow.server.XnioBufferPoolAdaptor类的一些代码示例,展示了XnioBufferPoolAdaptor类的具体用法。这些代码示例主要来源
本文整理了Java中io.undertow.server.XnioByteBufferPool类的一些代码示例,展示了XnioByteBufferPool类的具体用法。这些代码示例主要来源于Githu
我们目前正在调整使用 undertow 的服务,但找不到以下属性的默认值: server.undertow.worker-threads server.undertow.io-threads 我们了解
我有一个使用各种依赖项的应用程序。这些依赖项都使用了一堆乱七八糟的日志框架。由于我不希望任何库进行任何类型的日志记录,因此我有一个小程序试图将其全部禁用。 这已经运行了一段时间,但最近由于一些不为人知
我正在尝试使用 undertow.io 启动一个简单的 api 服务器API。这是我的启动代码。 this.server = Undertow.builder().addHttpListener(th
我的要求是提供“index.html”,无论请求中设置什么路由。我已经引用了Routing template format for undertow但无济于事。这似乎对人们有用。处理程序看起来像 Pa
我有一个简单的示例,其中我实现了一个访问日志处理程序。它确实记录到控制台。如何配置记录器记录到指定文件? package com.zetcode; import io.undertow.Underto
如 separate question 中所述,当使用Undertow时,所有处理都应该在专用的Worker线程池中完成,如下所示: public class Start { public sta
public class HelloWorldServer { public static void main(final String[] args) { Undertow
我正在尝试提供一个简单的“Hello world!”使用 Undertow 嵌入式服务器通过 HTTPS 使用自签名证书进行响应。但是,我在客户端 (Chrome) 上得到了 ERR_SSL_VERS
我有一个运行嵌入式 Undertow 的 Web 服务,一些处理程序利用常见的 Undertow 模式将请求卸载到工作线程: if (exchange.isInIoThread()) { ex
在 undertow documentation site 上列出的示例中,它展示了如何配置 2 个 servlet 及其映射。但我找不到如何配置默认 Servlet 以允许目录列表和资源服务。 De
我创建了一个网络服务器,允许我的网站通过 API 访问我的游戏数据。我的网络服务器看起来像这样(我正在使用 me.apachenick 框架) public class WebServer {
我正在与 Undertow 合作,我的目标是使用 AWS 实例获得最大吞吐量。 我面临的问题是: 当我使用一个线程数 = 1000 的实例时,我得到的吞吐量为 9900。当我使用两个线程数 = 100
根据the spec Undertow 有一个很好的基于文本的配置。 但是,我没有看到任何如何使用此类配置启动 Undertow 的示例代码。 如何使用 Undertow.builder()... 构
我是一名优秀的程序员,十分优秀!