복붙노트

[SPRING] WebSocket 핸드 셰이크 - 예기치 않은 응답 코드 200 - AngularJs 및 Spring Boot

SPRING

WebSocket 핸드 셰이크 - 예기치 않은 응답 코드 200 - AngularJs 및 Spring Boot

AngularJS 앱과 Spring Boot 사이에 websocket 통신을 설정하려고 할 때 오류가 발생했습니다 : websocket handshake 오류 - 예기치 않은 응답 코드 : 200.

다음은 JS 코드입니다.

function run(stateHandler, translationHandler, $websocket) {
    stateHandler.initialize();
    translationHandler.initialize();

    var ws = $websocket.$new('ws://localhost:8080/socket'); // instance of ngWebsocket, handled by $websocket service

    ws.$on('$open', function () {
        console.log('Oh my gosh, websocket is really open! Fukken awesome!');  
    });

    ws.$on('/topic/notification', function (data) {
        console.log('The websocket server has sent the following data:');
        console.log(data);

        ws.$close();
    });

    ws.$on('$close', function () {
        console.log('Noooooooooou, I want to have more fun with ngWebsocket, damn it!');
    });
}

그리고 여기 내 Java 코드가 있습니다.

@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry)
{
    stompEndpointRegistry.addEndpoint("/socket")
        .setAllowedOrigins("*")
        .withSockJS();
}

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableSimpleBroker("/topic");
}
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
    messages
        // message types other than MESSAGE and SUBSCRIBE
        .nullDestMatcher().authenticated()
        // matches any destination that starts with /rooms/
        .simpDestMatchers("/topic/tracker").hasAuthority(AuthoritiesConstants.ADMIN)
        .simpDestMatchers("/topic/**").permitAll()
        // (i.e. cannot send messages directly to /topic/, /queue/)
        // (i.e. cannot subscribe to /topic/messages/* to get messages sent to
        // /topic/messages-user<id>)
        .simpTypeMatchers(SimpMessageType.MESSAGE, SimpMessageType.SUBSCRIBE).denyAll()
        // catch all
        .anyMessage().denyAll();
}

누구든지이 문제를 해결하는 방법을 알고 있습니까? 미리 감사드립니다.

해결법

  1. ==============================

    1.비슷한 문제가 있었는데 크롬 플러그인 (Simple WebSocket Client)을 사용하여 websocket 연결을 테스트하고 ws : // localhost : 8080 / handler /에 연결하려고 시도했지만 내 코드에 registry.addEndpoint ( "/ handler "). setAllowedOrigins ("* "). withSockJS (); 예상치 못한 오류 200이 발생했습니다. 나는 크롬 확장에 내 클라이언트 요청 문자열에 / websocket을 추가하여이 문제를 해결했습니다. 따라서 JS 파일의 다음 줄을 변경하면됩니다.

    비슷한 문제가 있었는데 크롬 플러그인 (Simple WebSocket Client)을 사용하여 websocket 연결을 테스트하고 ws : // localhost : 8080 / handler /에 연결하려고 시도했지만 내 코드에 registry.addEndpoint ( "/ handler "). setAllowedOrigins ("* "). withSockJS (); 예상치 못한 오류 200이 발생했습니다. 나는 크롬 확장에 내 클라이언트 요청 문자열에 / websocket을 추가하여이 문제를 해결했습니다. 따라서 JS 파일의 다음 줄을 변경하면됩니다.

    var ws = $websocket.$new('ws://localhost:8080/socket');
    

     var ws = $websocket.$new('ws://localhost:8080/socket/websocket');
    

    나는 왜 이것을 해결할 수있는 이유를 알지 못한다. 내 경우에는 무작위로 우연히 발견된다.

  2. ==============================

    2.스프링 부트, WebSocket 및 각도 나는 똑같은 문제에 직면했다. 이것이 내가 그것을 해결하고 실시간 데이터와 함께 websocket을 실행하는 방법이다. 봄 부츠

    스프링 부트, WebSocket 및 각도 나는 똑같은 문제에 직면했다. 이것이 내가 그것을 해결하고 실시간 데이터와 함께 websocket을 실행하는 방법이다. 봄 부츠

    1. WebSocketConfig 클래스

    @Configuration
    @EnableWebSocketMessageBroker
    //@EnableScheduling
    public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    
        @Override
        public void configureMessageBroker(MessageBrokerRegistry messageBrokerRegistry) {
            messageBrokerRegistry
                    .enableSimpleBroker("/topic")
                    .setTaskScheduler(new DefaultManagedTaskScheduler())
                    .setHeartbeatValue(new long[] {0, 15000}); // heartbeatServer, heartbeatClient
    
            messageBrokerRegistry.setApplicationDestinationPrefixes("/app");
    
        }
    
        @Override
        public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
            stompEndpointRegistry
                    .addEndpoint("/ws/myapp")
                    .addInterceptors(new HttpHandshakeInterceptor())
                    .setAllowedOrigins("*");
    
            stompEndpointRegistry
                    .addEndpoint("/http/myapp")
                    .addInterceptors(new HttpSessionHandshakeInterceptor())
                    .setAllowedOrigins("*")
                    .withSockJS();
    
        }    
        @Override
        public void configureClientInboundChannel(ChannelRegistration channelRegistration) {
            channelRegistration.interceptors(new WebSocketChannelIntercepter());
        }
    
        @Override
        public void configureClientOutboundChannel(ChannelRegistration channelRegistration) {
            channelRegistration.interceptors(new WebSocketChannelIntercepter());
        }
    }
    

    2. Http HandshakeInterceptor 클래스

    public class HttpHandshakeInterceptor implements HandshakeInterceptor {
        public static final Logger logger = LoggerFactory.getLogger(HttpHandshakeInterceptor.class);
    
        @Override
        public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
            logger.info("Handshake interceptor called!!");
            if (request instanceof ServletServerHttpRequest) {
                ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
                HttpSession session = servletRequest.getServletRequest().getSession(false);
                if (session != null) {
                    attributes.put("sessionId", session.getId());
                }
            }
            logger.info("=> Attributes: " + attributes.toString());
            return true;
        }
    
        @Override
        public void afterHandshake(ServerHttpRequest request,
                                   ServerHttpResponse response,
                                   WebSocketHandler webSocketHandler,
                                   Exception e) {
    
        }
    }
    

    3. WebSecurityConfigurerAdapter 클래스

    @Configuration
    @EnableWebSecurity
    @EnableGlobalMethodSecurity(
            prePostEnabled = true,
            securedEnabled = true,
            jsr250Enabled = true
    )
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Autowired
        UserDetailsServiceImpl userDetailsService;
        @Autowired
        private JwtAuthEntryPoint unauthorizedHandler;
        @Bean
        public JwtAuthTokenFilter authenticationJwtTokenFilter() {
            return new JwtAuthTokenFilter();
        }
        @Override
        public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
            authenticationManagerBuilder
                    .userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());
        }
        @Bean
        @Override
        public AuthenticationManager authenticationManagerBean() throws Exception {
            return super.authenticationManagerBean();
        }
        @Bean
        public PasswordEncoder passwordEncoder() {
            return new BCryptPasswordEncoder();
        }
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .cors()
                    .and()
                    .csrf()
                    .disable()
                    .authorizeRequests()
                    .antMatchers("/", "/favicon.ico")                
                    .antMatchers("/api/stocks/**")
                    .permitAll()
                    .antMatchers("/ws/myapp", "/http/myaap", "/topic/**", "/app/**" )
                    .permitAll()
                    .anyRequest()
                    .authenticated()
                    .and()
                    .exceptionHandling()
                    .authenticationEntryPoint(unauthorizedHandler)
                    .and()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
            http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        }
    }
    

    모난 여기에 귀하의 서비스에서 사용할 URL은 다음과 같습니다.

    http://localhost:8080/http/myapp'
    ws://localhost:8080/ws/equities // this one is for live update
    

    이게 도움이되기를 바랍니다.

  3. from https://stackoverflow.com/questions/51845452/websocket-handshake-unexpected-response-code-200-angularjs-and-spring-boot by cc-by-sa and MIT license