Spring WebSocket 升级失败。响应 400 BAD_REQUEST

问题描述 投票:0回答:1

我有一个带有 Stomp WebSocket 的 Spring 应用程序,但是当我尝试使用 Postman 或 wscat 连接到它时,我收到“错误:意外的服务器响应:400”

这是我使用的配置代码:

WebSocketConfig

@Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        System.out.println("Registering Stomp Endpoints");
        try {
            registry.addEndpoint("/chat-service")
                    .setAllowedOrigins("*")
                    .addInterceptors(new HandshakeDebugInterceptor())
                    .withSockJS();
            System.out.println("Stomp Endpoints Registered Successfully");
        } catch (Exception e) {
            System.out.println("Error registering Stomp Endpoints: " + e.getMessage());
        }
    }

安全配置

@Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .cors(Customizer.withDefaults())
                .authorizeHttpRequests((authorize) -> {
                            authorize
                                    .requestMatchers("/api/auth/*").permitAll()
                                    .requestMatchers("/chat-service/**").permitAll()
                                    .requestMatchers("/admin/**").hasRole("ADMIN")
                                    //.anyRequest().authenticated();
                                    .anyRequest().permitAll();
                        }
                )
                .sessionManagement((configurer) -> {
                    configurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
                .authenticationProvider(authenticationProvider)
                .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
                .logout(Customizer.withDefaults()
                );

                http.addFilterBefore((request, response, chain) -> {
                    HttpServletRequest httpRequest = (HttpServletRequest) request;
                    HttpServletResponse httpResponse = (HttpServletResponse) response;
                    System.out.println("Request to: " + httpRequest.getRequestURI());
                    System.out.println("Method: " + httpRequest.getMethod());
                    System.out.println("Headers: " + httpRequest.getHeaderNames());
                    System.out.println("User Principal: " + httpRequest.getUserPrincipal());
                    System.out.println("Authentication: " + SecurityContextHolder.getContext().getAuthentication());
                    chain.doFilter(httpRequest, httpResponse);
                }, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

所有其他端点(例如注册或登录)均正常工作 我在

securityFilterChain
OncePerRequestFilter
过滤器中添加了很多日志记录,但我可以找到导致 400 响应的任何有用信息。

这是我运行时来自服务器的日志(http:// 和 ws:// 的响应相同)

wscat -c ws://localhost:8081/chat-service
  : Securing GET /chat-service
Request to: /chat-service
Method: GET
Headers: org.springframework.security.web.firewall.StrictHttpFirewall$StrictFirewalledRequest$2@5118325e
User Principal: null
Authentication: null
2024-04-01T21:11:26.365+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.s.w.a.AnonymousAuthenticationFilter  : Set SecurityContextHolder to anonymous SecurityContext
2024-04-01T21:11:26.366+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.security.web.FilterChainProxy      
  : Secured GET /chat-service
2024-04-01T21:11:26.367+03:00  INFO 21456 --- [messenger] [nio-8081-exec-7] c.m.m.c.RequestResponseLoggingFilter   
  : Request: GET /chat-service
2024-04-01T21:11:26.367+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.web.servlet.DispatcherServlet      
  : GET "/chat-service", parameters={}
2024-04-01T21:11:26.368+03:00 DEBUG 21456 --- [messenger] [nio-8081-exec-7] o.s.web.servlet.DispatcherServlet      
  : Completed 400 BAD_REQUEST
2024-04-01T21:11:26.369+03:00  INFO 21456 --- [messenger] [nio-8081-exec-7] c.m.m.c.RequestResponseLoggingFilter   
  : Response: 400 null

java spring spring-websocket stomp bad-request
1个回答
0
投票

因此,我提高了日志记录级别并在

application.properties
中为整个 .web 启用 TRACE,我在日志中得到了一些有趣的结果:

2024-04-02T13:07:02.461+03:00 TRACE 9164 --- [messenger] [nio-8081-exec-1] o.s.w.s.s.s.WebSocketHandlerMapping     
 : Mapped to HandlerExecutionChain with [org.springframework.web.socket.sockjs.support.SockJsHttpRequestHandler@3c1afe71] and 1 interceptors
2024-04-02T13:07:02.477+03:00 DEBUG 9164 --- [messenger] [nio-8081-exec-1] o.s.w.s.s.t.h.DefaultSockJsService      
 : Processing transport request: GET http://localhost:8081/chat-service
2024-04-02T13:07:02.479+03:00 TRACE 9164 --- [messenger] [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet       
 : No view rendering, null ModelAndView returned.
2024-04-02T13:07:02.482+03:00 DEBUG 9164 --- [messenger] [nio-8081-exec-1] o.s.web.servlet.DispatcherServlet       
 : Completed 400 BAD_REQUEST, headers={masked}
2024-04-02T13:07:02.485+03:00  INFO 9164 --- [messenger] [nio-8081-exec-1] c.m.m.c.RequestResponseLoggingFilter    

在 DispatcherServlet 400 响应之前是来自 SockJS 的一些日志,所以我从 WebSocketConfig 中删除 .withSockJS() ,现在我可以从 postman 或 wscat 连接到我的应用程序,但我认为当应用程序客户端准备就绪时,必须将这个东西带回来

© www.soinside.com 2019 - 2024. All rights reserved.