Ошибка во время рукопожатия WebSocket: неожиданный код ответа: 200 в приложении JHipster

#spring-boot #websocket #jhipster #stomp #sockjs

#весенняя загрузка #websocket #jhipster #топать #sockjs

Вопрос:

Я пытаюсь подключиться к websocket в моем существующем приложении Jhipster, которое построено с использованием Java spring и Angular 8. Во время создания проекта я не выбрал опцию websocket, и теперь есть необходимость реализовать websocket в проекте. Я воспользовался помощью «https://www.jhipster.tech/using-websockets /» и попытался реализовать то же самое решение, но я получаю сообщение об ошибке рукопожатия. Я использую STOMP и SockJS для в websockets. Пожалуйста, дайте мне знать, что может быть причиной сбоя рукопожатия.

Вот конфигурация websocket.java-файл.

 
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

import hr.nic.vc.security.AuthoritiesConstants;

import java.security.Principal;

import org.springframework.http.server.*;

import java.util.*;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.server.*;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.config.annotation.*;
import org.springframework.web.socket.server.HandshakeInterceptor;
import org.springframework.web.socket.server.support.DefaultHandshakeHandler;

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfiguration implements WebSocketMessageBrokerConfigurer {

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

  @Override
  public void registerStompEndpoints(StompEndpointRegistry
   registry) {
    registry.addEndpoint("/websocket/blog").setHandshakeHandler(defaultHandshakeHandler())
        .setAllowedOrigins("*").withSockJS();
  }
  
  @Bean
  public HandshakeInterceptor httpSessionHandshakeInterceptor() {
      return new HandshakeInterceptor() {

          @Override
          public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
              if (request instanceof ServletServerHttpRequest) {
                  ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                  attributes.put(IP_ADDRESS, servletRequest.getRemoteAddress());
              }
              return true;
          }

          @Override
          public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {

          }
      };
  }

  private DefaultHandshakeHandler defaultHandshakeHandler() {
      return new DefaultHandshakeHandler() {
          @Override
          protected Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
              Principal principal = request.getPrincipal();
              if (principal == null) {
                  Collection<SimpleGrantedAuthority> authorities = new ArrayList<>();
                  authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
                  principal = new AnonymousAuthenticationToken("WebsocketConfiguration", "anonymous", authorities);
              }
              return principal;
          }
      };
  }
  
}
  

И это файл безопасности websocket.

 public class WebsocketSecurityConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
      protected void configureInbound(MessageSecurityMetadataSourceRegistry messages)
      {
        messages.nullDestMatcher().authenticated().simpDestMatchers("/topic/blog")
            .authenticated()
            // matches any destination that starts with /topic/
            // (i.e. cannot send messages directly to /topic/)
            // (i.e. can’t subscribe to /topic/messages/* to get messages which is sent to
            // /topic/messages-user)
            .simpDestMatchers("/topic/**").authenticated();
            // message types other than MESSAGE and SUBSCRIBE
            //.simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
            // catch all
            //.anyMessage().denyAll();
      }
    /**
     * Disables CSRF for Websockets.
     */
    @Override
    protected boolean sameOriginDisabled() {
        return true;
    }
}
  

Вот метод connect, который вызывается после аутентификации для подключения websocket.

 connect():void {
    console.log("connect called"); //eslint-disable-line
    // build absolute path, websocket doesn't fail during deploying with a context path
    let url = '/websocket/blog';
    url = this.location.prepareExternalUrl(url);
    const authToken = this.authServerProvider.getToken();
    if (authToken) {
      url  = '?access_token='   authToken;
    }
    const socket = new SockJS(url);
    this.stompClient = Stomp.over(socket);
    const headers = {};
    this.stompClient.connect(headers, () => {
        console.log("this is inside stompclient connect connect"); //eslint-disable-line
      this.stompClient.subscribe('/topic/blog', data => {
          console.log("This inside subscription"); //eslint-disable-line
        this.listenerObserver.next(JSON.parse(data.body));
      });
    });
  }
}
  

Токен авторизации передается с правильным значением. Следовательно, ошибки в авторизации нет.
Пожалуйста, дайте мне знать, если потребуется что-нибудь еще.
Я застрял на этом этапе уже довольно давно.

Ошибка:

 WebSocket connection to 'ws://localhost:8080/websocket/blog/587/mklduqvp/websocket?access_token=eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJoYXJkZWVwc2h1a2xhMDhAbmljLmluIiwiYXV0aCI6IlJPTEVfRU1QTE9ZRUUiLCJleHAiOjE2MDUyNDUwNjd9.DJ2HITaVAiaphd2yg3yPAiLrLI4n8MjszjBasC3zOHrC-73mFdltDPEYHihY16VzPv0rh6EYLj84zCBv37TDNA' failed: Error during WebSocket handshake: Unexpected response code: 200
  

Комментарии:

1. Вы пробовали создать новый проект с теми же настройками, что и у старого, и скопировать конфигурацию?

2. Да, я пробовал это. Все еще не повезло. Та же ошибка, что и выше.

3. Недавно созданный проект работает нормально. Я пытаюсь добавить конфигурацию websocket в существующий проект. Также я обновил ошибку. Пожалуйста, посмотрите

4. Версия Jhipster одинакова для нового и старого проекта. Да, я проверил журналы на стороне сервера, ошибок не было, только на стороне клиента эта ошибка была показана. Я не запускал сервер в отладчике, поскольку оба проекта совершенно разные.

5. Отладчик покажет вам выполнение в посреднике сообщений, который не является вашим кодом, поэтому он одинаков для обоих проектов, только его инициализация должна отличаться и вызывать разное поведение. Журналы сервера, вероятно, не находятся на уровне отладки org.springframework.web.socket , поэтому вы не можете видеть, что происходит с comapre.

Ответ №1:

В вашем DefaultHandshakeHandler вы можете попробовать аннотировать @Bean и установить значение public.

 @Bean
public DefaultHandshakeHandler defaultHandshakeHandler() {
  

Комментарии:

1. Спасибо за ответ, но я уже пробовал это. Все еще получаю ту же ошибку.