Websockets using "SockJS+spring websocket" error when trying to connect the websocket (404: path of STOMP endpoint not found)

huangapple go评论146阅读模式
英文:

Websockets using "SockJS+spring websocket" error when trying to connect the websocket (404: path of STOMP endpoint not found)

问题

以下是您提供的内容的翻译:

在我的网络应用程序中,我尝试使用SockJS连接到WebSocket,但返回了错误消息(404路径"/stomp/info"未找到):

这个问题已经被问过很多次了,但我没有找到适合我情况的答案。
有人能帮我找到解决方案吗?

这是我的代码

- 基于Spring WebFlux、Spring Security(JWT)的服务器端 [Spring Boot 版本:2.1.2 RELEASE]

WebSocketConfig.java

  1. @Configuration
  2. @EnableWebSocketMessageBroker
  3. public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
  4. @Override
  5. public void configureMessageBroker(MessageBrokerRegistry registry) {
  6. registry.enableSimpleBroker("/prob");
  7. registry.setApplicationDestinationPrefixes("/app");
  8. registry.setUserDestinationPrefix("/prob");
  9. }
  10. @Override
  11. public void registerStompEndpoints(StompEndpointRegistry registry) {
  12. registry
  13. .addEndpoint("/stomp")
  14. .setAllowedOrigins("http://localhost:4200")
  15. //.setAllowedOrigins("*")
  16. .withSockJS();
  17. }
  18. @Override
  19. public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
  20. DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
  21. resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
  22. MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
  23. converter.setObjectMapper(new ObjectMapper());
  24. converter.setContentTypeResolver(resolver);
  25. messageConverters.add(converter);
  26. return false;
  27. }
  28. }

CORSFilter.java

  1. @Configuration
  2. @EnableWebFlux
  3. public class CORSFilter implements WebFluxConfigurer {
  4. @Override
  5. public void addCorsMappings(CorsRegistry registry) {
  6. registry.addMapping("/**")
  7. .allowedOrigins("*")
  8. .allowedMethods("*")
  9. .allowedHeaders("*")
  10. .exposedHeaders("Access-Control-Allow-Origin",
  11. "Access-Control-Allow-Methods",
  12. "Access-Control-Allow-Headers",
  13. "Access-Control-Max-Age",
  14. "Access-Control-Request-Headers",
  15. "Access-Control-Request-Method")
  16. .maxAge(3600)
  17. .allowCredentials(false);
  18. }
  19. }

WebSecurityConfig.java

  1. @EnableWebFluxSecurity
  2. @EnableReactiveMethodSecurity
  3. @Configuration
  4. public class WebSecurityConfig {
  5. @Autowired
  6. private AuthenticationManager authenticationManager;
  7. @Autowired
  8. private SecurityContextRepository securityContextRepository;
  9. @Bean
  10. public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
  11. return http
  12. .cors().and().headers().frameOptions().disable().and()
  13. .csrf().disable()
  14. .formLogin().disable()
  15. .httpBasic().disable()
  16. .authenticationManager(authenticationManager)
  17. .securityContextRepository(securityContextRepository)
  18. .authorizeExchange()
  19. .pathMatchers(HttpMethod.OPTIONS).permitAll()
  20. .pathMatchers("/login","/stomp","/stomp/**","/stomp/info","/stomp/info/**").permitAll()
  21. .anyExchange().authenticated()
  22. .and().build();
  23. }
  24. }

- 基于Angular的客户端(stompjs + sockjs-client)

  1. socketConnect() {
  2. const socket = new SockJS('http://localhost:8081/stomp');
  3. this.stompClient = StompJS.Stomp.over(socket);
  4. const _this = this;
  5. this.stompClient.connect({}, function (frame) {
  6. console.log('Connected: ' + frame);
  7. _this.stompClient.subscribe('/prob/' + _this.id + '/newcomment', function (data) {
  8. console.log(data);
  9. });
  10. });
  11. }

更新

我更改了CORS过滤器的配置:

  1. @Configuration
  2. public class CORSFilter {
  3. @Bean
  4. CorsWebFilter corsWebFilter() {
  5. CorsConfiguration config = new CorsConfiguration();
  6. config.setAllowCredentials(true);
  7. config.addAllowedOrigin("http://localhost:4200");
  8. config.addAllowedHeader("*");
  9. config.addAllowedMethod("*");
  10. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  11. source.registerCorsConfiguration("/**", config);
  12. return new CorsWebFilter(source);
  13. }
  14. }

但我仍然遇到另一个错误:
>GET http://localhost:8081/stomp/info?t=1602859336795 404 (未找到)

以下是服务器端初始化WebSocket的日志:

  1. 2020-10-16 15:41:14.712 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : Starting...
  2. 2020-10-16 15:41:14.712 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : BrokerAvailabilityEvent[available=true, SimpleBrokerMessageHandler [DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]]
  3. 2020-10-16 15:41:14.714 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : Started.
  4. ...
  5. 2020-10-16 15:42:13.750 INFO 13060 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]
英文:

In my web application, i tried to connect to the websocket using SockJS, but an error message is returned (404 path "/stomp/info" not found) :

This question is asked numerous times, but i fail to find an answer for my situation
Could anyone help me to find the solution ?

Here is my code

- Server side based on spring web flux, spring security (JWT) [spring boot version: 2.1.2RELEASE]

WebSocketConfig.java

  1. @Configuration
  2. @EnableWebSocketMessageBroker
  3. public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
  4. @Override
  5. public void configureMessageBroker(MessageBrokerRegistry registry) {
  6. registry.enableSimpleBroker(&quot;/prob&quot;);
  7. registry.setApplicationDestinationPrefixes(&quot;/app&quot;);
  8. registry.setUserDestinationPrefix(&quot;/prob&quot;);
  9. }
  10. @Override
  11. public void registerStompEndpoints(StompEndpointRegistry registry) {
  12. registry
  13. .addEndpoint(&quot;/stomp&quot;)
  14. .setAllowedOrigins(&quot;http://localhost:4200&quot;)
  15. //.setAllowedOrigins(&quot;*&quot;)
  16. .withSockJS();
  17. }
  18. @Override
  19. public boolean configureMessageConverters(List&lt;MessageConverter&gt; messageConverters) {
  20. DefaultContentTypeResolver resolver = new DefaultContentTypeResolver();
  21. resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
  22. MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
  23. converter.setObjectMapper(new ObjectMapper());
  24. converter.setContentTypeResolver(resolver);
  25. messageConverters.add(converter);
  26. return false;
  27. }
  28. }

CORSFilter.java

  1. @Configuration
  2. @EnableWebFlux
  3. public class CORSFilter implements WebFluxConfigurer {
  4. @Override
  5. public void addCorsMappings(CorsRegistry registry) {
  6. registry.addMapping(&quot;/**&quot;)
  7. .allowedOrigins(&quot;*&quot;)
  8. .allowedMethods(&quot;*&quot;)
  9. .allowedHeaders(&quot;*&quot;)
  10. .exposedHeaders(&quot;Access-Control-Allow-Origin&quot;,
  11. &quot;Access-Control-Allow-Methods&quot;,
  12. &quot;Access-Control-Allow-Headers&quot;,
  13. &quot;Access-Control-Max-Age&quot;,
  14. &quot;Access-Control-Request-Headers&quot;,
  15. &quot;Access-Control-Request-Method&quot;)
  16. .maxAge(3600)
  17. .allowCredentials(false);
  18. }
  19. }

WebSecurityConfig.java

  1. @EnableWebFluxSecurity
  2. @EnableReactiveMethodSecurity
  3. @Configuration
  4. public class WebSecurityConfig {
  5. @Autowired
  6. private AuthenticationManager authenticationManager;
  7. @Autowired
  8. private SecurityContextRepository securityContextRepository;
  9. @Bean
  10. public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
  11. return http
  12. .cors().and().headers().frameOptions().disable().and()
  13. .csrf().disable()
  14. .formLogin().disable()
  15. .httpBasic().disable()
  16. .authenticationManager(authenticationManager)
  17. .securityContextRepository(securityContextRepository)
  18. .authorizeExchange()
  19. .pathMatchers(HttpMethod.OPTIONS).permitAll()
  20. .pathMatchers(&quot;/login&quot;,&quot;/stomp&quot;,&quot;/stomp/**&quot;,&quot;/stomp/info&quot;,&quot;/stomp/info/**&quot;).permitAll()
  21. .anyExchange().authenticated()
  22. .and().build();
  23. }
  24. }

- Client side based on Angular (stompjs + sockjs-client)

  1. socketConnect() {
  2. const socket = new SockJS(&#39;http://localhost:8081/stomp&#39;);
  3. this.stompClient = StompJS.Stomp.over(socket);
  4. const _this = this;
  5. this.stompClient.connect({}, function (frame) {
  6. console.log(&#39;Connected: &#39; + frame);
  7. _this.stompClient.subscribe(&#39;/prob/&#39; + _this.id + &#39;/newcomment&#39;, function (data) {
  8. console.log(data);
  9. });
  10. });
  11. }

UPDATE

I changed the configuration of the CORS Filter :

  1. @Configuration
  2. public class CORSFilter{
  3. @Bean
  4. CorsWebFilter corsWebFilter(){
  5. CorsConfiguration config = new CorsConfiguration();
  6. config.setAllowCredentials(true);
  7. config.addAllowedOrigin(&quot;http://localhost:4200&quot;);
  8. config.addAllowedHeader(&quot;*&quot;);
  9. config.addAllowedMethod(&quot;*&quot;);
  10. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
  11. source.registerCorsConfiguration(&quot;/**&quot;,config);
  12. return new CorsWebFilter(source);
  13. }

But i still having an other error :
>GET http://localhost:8081/stomp/info?t=1602859336795 404 (not found)

Here is the logs of initialization of websocket in the server side :

  1. 2020-10-16 15:41:14.712 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : Starting...
  2. 2020-10-16 15:41:14.712 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : BrokerAvailabilityEvent[available=true, SimpleBrokerMessageHandler [DefaultSubscriptionRegistry[cache[0 destination(s)], registry[0 sessions]]]]
  3. 2020-10-16 15:41:14.714 INFO 13060 --- [ restartedMain] o.s.m.s.b.SimpleBrokerMessageHandler : Started.
  4. ...
  5. 2020-10-16 15:42:13.750 INFO 13060 --- [MessageBroker-1] o.s.w.s.c.WebSocketMessageBrokerStats : WebSocketSession[0 current WS(0)-HttpStream(0)-HttpPoll(0), 0 total, 0 closed abnormally (0 connect failure, 0 send limit, 0 transport error)], stompSubProtocol[processed CONNECT(0)-CONNECTED(0)-DISCONNECT(0)], stompBrokerRelay[null], inboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], outboundChannel[pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 0], sockJsScheduler[pool size = 1, active threads = 1, queued tasks = 0, completed tasks = 0]

答案1

得分: 1

最后我找到了问题,
问题是我在spring-mvc中使用了websocket配置而不是spring-webflux,我找到了一个很好的教程,可以在spring-webflux的响应式上下文中实现websocket:链接描述在此

英文:

And finally i found the issue,
the problem is i used websocket configuration for spring-mvc and not spring-webflux, i found a good tuto to implement websocket in reactive context with spring-webflux : enter link description here

huangapple
  • 本文由 发表于 2020年10月15日 06:39:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/64362455.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定