Spring Websocket ChannelInterceptor не запускает событие CONNECT

Я пишу простое приложение Stomp Websocket с помощью Spring, а клиенты являются как веб-(JS), так и мобильными (ios, android). Из клиента кода JS, подключающегося через SockJS, в то время как мобильные клиенты используют простое соединение через веб-сокет за SockJS. Проблема в том, что поведение в моем ChannelInterceptor, где я проверяю аутентификацию, совершенно разное для разных типов подключений. Я не могу заставить его работать одинаково для каждого клиента. Позвольте мне вкратце привести некоторый код, стоящий за этим, и объяснить на примере: стартер Websocket был взят из примера Spring здесь: https://github.com/spring-guides/gs-messaging-stomp-websocket.git

Конфигурация веб-сокета:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/gs-guide-websocket")
                .setAllowedOrigins("*")
                .withSockJS();
    }

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new MyChannelInterceptor());
    }
}

И сам ChannelInterceptor:

public class MyChannelInterceptor implements ChannelInterceptor {
    @Override
    public void postSend(Message<?> message, MessageChannel channel, boolean sent) {
        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
        StompCommand command = accessor.getCommand();
        ...
    }
}

Когда я подключаюсь через SockJS из приложения JS (http://localhost:8080/gs-guide-websocket - и пусть Spring SockJS сделает все остальное):

  1. Я могу поймать команду CONNECT в MyChannelInterceptor, в методе postSend - ОК
  2. Когда я закрываю соединение, там же DISCONNECT команда запускается ДВАЖДЫ. - Не хорошо

Когда я подключаюсь через Websocket за SockJS (ws: // localhost: 8080 / gs-guide-websocket / websocket):

  1. Я НЕ МОГУ поймать команду CONNECT в MyChannelInterceptor, в методе postSend - КРИТИЧНО
  2. Когда я закрываю соединение, команда DISCONNECT запускается правильно один раз. - OK

В принципе, хотя я не могу понять, почему sockjs пытается отключиться дважды, я могу с этим жить. Но с перехватчиком, который не улавливает каждое событие подключения - я не могу жить, так как я собираюсь отслеживать сеанс пользователя и сохранять их именно от этого перехватчика.

  • Я уже пытался удалить .withSockJs() в конфиге - и просто подключиться к сокету - та же проблема
  • Я также пытался реализовать прослушиватель событий приложения на SessionConnectEvent и SessionConnectedEvent - та же проблема

Теперь я полностью застрял и не знаю, куда еще я могу пойти отсюда ... Любая помощь или отправная точка приветствуются.

Большое спасибо за внимание к моей боли = (


person DruidKuma    schedule 24.12.2019    source источник


Ответы (1)


После публикации проблемы в Spring Github и общения там я обнаружил, что это не ошибка и, по сути, не проблема, а просто моя вина:

  • Ожидается поведение DISCONNECT. Он упоминается в нескольких местах документации Spring WebSocket в главах «Перехват», «События» и «Мониторинг».
  • Событие CONNECT не должно запускаться при подключении через простые веб-сокеты, потому что оно просто устанавливает соединение по простому протоколу WebSocket, а для событий STOMP вам необходимо использовать клиент STOMP.

Для заинтересованных, пожалуйста, обратитесь к соответствующей теме: https://github.com/spring-projects/spring-framework/issues/24269

person DruidKuma    schedule 08.01.2020