如何在Spring Boot WebSocket应用程序中修复跨域资源共享的问题''Access-Control-Allow-Origin''?

4

大家好,我是新手,正在学习Spring Boot和Websocket。这是我第一个整合React和Spring Boot的项目,目前正在使用WebSocket构建后端聊天应用。

正如所提到的,我的前端是在React (localhost:3000)中构建的,但是在尝试调用后端/聊天应用程序时,我遇到了错误:

Access to XMLHttpRequest at 'http://localhost:9090/ws/info?t=1652731448126' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.

我尝试查找了一些可能的解决方案,比如使用@CrossOrigin(origins = "https://localhost:3000")@CrossOrigin(origins = "http://localhost:3000"),但这并没有改变任何东西。我还尝试了使用@CrossOrigin(origins = "*"),但是没有成功。两种尝试都导致了相同的错误信息。

聊天控制器:

package com.project2.chatapi.controller;

import com.project2.chatapi.models.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;

@CrossOrigin(origins = "https://localhost:3000")
@Controller
public class ChatController {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    /**
     * Handles messages coming into the public chatroom
     * @param message
     * @return message
     */
    @MessageMapping("/message")  // /app/message
    @SendTo("/chatroom/public")
    public Message receivePublicMessage(@Payload Message message) {
        return message;
    }

    /**
     * Handles messages being sent to a private chat
     * Receives the message from a user and sends to another user
     * @param message
     * @return message
     */
    @MessageMapping("/private-message")
    public Message receivePrivateMessage(@Payload Message message) {
        simpMessagingTemplate.convertAndSendToUser(message.getReceiverName(), "/private", message); // listens to /user/name/private
        return message;
    }
}

WebsocketConfig类:

package com.project2.chatapi.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {

    /**
     * Adding endpoint to the chat
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws")
                .setAllowedOriginPatterns("http://localhost:3000")
                .withSockJS();
    }

    /**
     * Configuring application destination prefixes
     * Adding topic prefixes - chatroom, and user
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/chat");
        registry.enableSimpleBroker("/chatroom","/user");
        registry.setUserDestinationPrefix("/user");
    }

    @Bean
    public WebMvcConfigurer corsConfig() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowedOrigins("http://localhost:3000");
            }
        };
    }
}

调用后端的 React 方法:

    const connect = (e) => {
        e.preventDefault();
        setUserData({...userData, "username": username});
        let Sock = new SockJS('http://localhost:9090/ws');
        stompClient = over(Sock);
        stompClient.connect({},onConnected, onError);
    }

我也尝试了一些关于setAllowedOrigins的不同解决方案。我尝试了几种组合,包括("http://localhost:3000")和("*")--但似乎没有改变我的错误信息。
我已经困在这里好几天了,任何帮助都将不胜感激。谢谢!
更新: 自从发布这个问题以来,我尝试了以下额外的方法。不幸的是,这些尝试仍然会出现相同的错误。
1.我尝试添加一个过滤器。
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class SimpleCORSFilter implements Filter {

    final Logger logger = LoggerFactory.getLogger(SimpleCORSFilter.class);

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        logger.info("Initializing Middleware");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest requestToUse = (HttpServletRequest)servletRequest;
        HttpServletResponse responseToUse = (HttpServletResponse)servletResponse;

        responseToUse.setHeader("Access-Control-Allow-Origin",requestToUse.getHeader("Origin"));
        filterChain.doFilter(requestToUse,responseToUse);
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }
}
  1. 我尝试在我的配置文件中添加cors映射
  2. 我还尝试在我的配置文件中添加CorsConfirgurationSource
@Configuration
@EnableWebSocketMessageBroker
public class WebsocketConfig implements WebSocketMessageBrokerConfigurer {

    // can possibly delete
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowCredentials(false)
                .maxAge(3600)
                .allowedHeaders("Accept", "Content-Type", "Origin",
                        "Authorization", "X-Auth-Token")
                .exposedHeaders("X-Auth-Token", "Authorization")
                .allowedMethods("POST", "GET", "DELETE", "PUT", "OPTIONS");
    }

    /**
     * Adding endpoint to the chat
     * @param registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws/*")
                .setAllowedOrigins("http://localhost:3000")
                .withSockJS();
    }

    /**
     * Configuring application destination prefixes
     * Adding topic prefixes - chatroom, and user
     * @param registry
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.setApplicationDestinationPrefixes("/chat");
        registry.enableSimpleBroker("/chatroom","/user");
        registry.setUserDestinationPrefix("/user");
    }
//
    @Bean
    public WebMvcConfigurer corsConfig() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/ws/**")
                        .allowedMethods("GET", "POST", "PUT", "DELETE")
                        .allowedHeaders("*")
                        .allowedOrigins("http://localhost:3000");
            }
        };
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setExposedHeaders(Arrays.asList("Authorization"));
        configuration.addAllowedOrigin("http://localhost:3000");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.applyPermitDefaultValues();
        return source;
    }
}
  1. 将CORS映射和WebMvcConfigurer添加到我的主应用程序中
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/*").allowedOrigins("http://localhost:3000");
            }
        };
    }

enter image description here 我在谷歌浏览器的网络日志中检查了所有配置,但仍然显示Access-Control-Allow-Origin: *


也许可以将.allowCredentials(false)更改为.allowCredentials(true),因为您已经设置了Authorization头? - Normal
也许这可以帮助你?https://dev59.com/e1wY5IYBdhLWcg3wpJA- - Normal
我目前在此聊天中未使用JWT或Web令牌。因此也不完全适用。 - may cheynack
你找到解决方案了吗?我也遇到了同样的问题。 - thahgr
2个回答

1

这解决了我的问题

 @Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry
    .setAllowedOrigins("http://localhost:3000") // not setAllowedOriginPatterns  
    .withSockJS();
}

0
在我的情况下,我是这样解决的。由于我正在本地测试它,所以它是本地主机,对于生产环境,请删除本地主机。
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

@Configurable
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    private String url = "http://localhost:4200";

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/chat-websocket")
        .setAllowedOrigins(url)
        .withSockJS();

    }

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

    @Bean
    WebMvcConfigurer corsConfig() {
        return new WebMvcConfigurer() {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/ws/**")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowedOrigins(url);
            }
        };
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接