Контекст
В настоящее время мы настраиваем проект Springboot, используя Apache Camel в качестве инфраструктуры интеграции.
В конце нашего маршрута нам нужно отправлять сообщения с протоколом веб-сокетов WSS, где наше приложение действует как клиент и должно отправлять сообщения на удаленный сервер, который предоставляет конечную точку веб-сокета.
Но удаленный сервер сначала требует аутентификацию во время рукопожатия WSS. На самом деле для этого требуются определенные заголовки HTTP, включая заголовок Authorization: Bearer {jwt-bearer-token}
. Токен требуется только во время рукопожатия. После того, как веб-розетка была открыта, больше не требуется дополнительная аутентификация.
1010 * подход *
Поскольку это, похоже, единственный клиентский компонент веб-сокета для Apache Camel, мы намеревались использовать AHC-WS компонент , как показано в POM
ниже:
...
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
<version>3.0.0-M2</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-ahc-ws</artifactId>
<version>3.0.0-M2</version>
</dependency>
...
В нашем определении маршрута мы затем добавляем необходимые заголовки к сообщению (например, заголовок Authorization
с токеном-носителем JWT). Кроме того, мы регистрируем токен, чтобы увидеть, действительно ли он добавлен в качестве заголовка сообщения (что это такое).
<?xml version="1.0" encoding="UTF-8"?>
<routes xmlns="http://camel.apache.org/schema/spring">
<route id="distributorRoute">
<from uri="seda:distributorEntryPoint"/>
<setHeader headerName="Authorization">
<simple>Bearer {jwt-bearer-token}</simple>
</setHeader>
<log message="${header.Authorization}"/>
<to uri="ahc-wss://{remote-server-wss-endpoint}>
</route>
</routes>
Проблема
Проще говоря, сообщения не могут быть отправлены через WSS, и кажется, что соединение никогда не устанавливается.
Приложение выдает следующее исключение NPE:
2019-06-07 15:52:00.304 INFO 17164 --- [butorEntryPoint] o.a.camel.component.ahc.ws.WsEndpoint : Reconnecting websocket: wss://{remote-server-wss-endpoint}
...
java.lang.NullPointerException: null
at org.apache.camel.component.ahc.ws.WsProducer.sendMessage(WsProducer.java:76) ~[camel-ahc-ws-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.component.ahc.ws.WsProducer.process(WsProducer.java:51) ~[camel-ahc-ws-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.support.AsyncProcessorConverterHelper$ProcessorToAsyncProcessorBridge.process(AsyncProcessorConverterHelper.java:66) ~[camel-support-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.processor.SendProcessor.process(SendProcessor.java:130) ~[camel-core-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.processor.RedeliveryErrorHandler$RedeliveryState.run(RedeliveryErrorHandler.java:482) ~[camel-core-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.support.ReactiveHelper$Worker.schedule(ReactiveHelper.java:130) [camel-support-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.support.ReactiveHelper.scheduleMain(ReactiveHelper.java:43) [camel-support-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.processor.Pipeline.process(Pipeline.java:88) [camel-core-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.processor.CamelInternalProcessor.process(CamelInternalProcessor.java:221) [camel-core-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.component.seda.SedaConsumer.sendToConsumers(SedaConsumer.java:289) [camel-seda-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.component.seda.SedaConsumer.doRun(SedaConsumer.java:203) [camel-seda-3.0.0-M2.jar:3.0.0-M2]
at org.apache.camel.component.seda.SedaConsumer.run(SedaConsumer.java:148) [camel-seda-3.0.0-M2.jar:3.0.0-M2]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1135) [na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [na:na]
at java.base/java.lang.Thread.run(Thread.java:844) [na:na]
Во время отладки мы обнаружили, что org.apache.camel.component.ahc.ws.WsProducer
пытается отправить сообщение с объектом org.apache.camel.component.ahc.ws.WebSocket
, в нашем случае null
:
Однако компонент, кажется, подключен правильно, поскольку отправка на незащищенную конечную точку WS для целей тестирования работала как ожидалось. Затем он также создает журнал «Переподключение веб-сокета» только один раз.
Вопросы
Кто-нибудь уже сталкивался с подобной проблемой при аутентификации во время рукопожатия WS?
Мы уже изучили возможности конфигурации компонента AHC-WS, но ни одна из них, похоже, не подходит для этого случая.
Кроме того, нам нужно динамически генерировать и добавлять токен, поэтому жесткое кодирование не поможет.