vue、springboot集成websocket跨域问题解决

       由于浏览器连接的是服务器上的websocket,导致出现了如下跨域错误:

vue、springboot集成websocket跨域问题解决_第1张图片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'. Origin 'http://a.com' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute。

     先分析下出现这个问题的原因:由于前后端分离导致我们通常会写跨域配置(如下代码)。但是报错很明显指出request's credentials mode is 'include',那么响应就the response must not be the wildcard '*’。所以直接配置Access-Control-Allow-Origin的值为通配是行不通的。具体怎么解决我接下来会讲。

package cn.datainvest.core.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 解决跨越配置类
 * @author yangfeng
 *
 */
@Configuration
public class CorsConfig {

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }

    /**
     * 跨域过滤器
     *
     * @return
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }
}

springboot集成websocket步骤如下:

1.引入依赖

        
        
            org.springframework.boot
            spring-boot-starter-websocket
        

2:WebSocketConfig

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;

/**
 * @author yangfeng
 **/
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket").setAllowedOrigins("*").withSockJS();
    }

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

3.业务代码

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;


@Component
public class Weather {

    @Resource
    private IWeatherService weatherService;

    private static Logger LOG = LoggerFactory.getLogger(WeatherScheduler.class);

    @Autowired
    private SimpMessagingTemplate messagingTemplate;


    /**
     * 保存天气信息
     */
    public void saveWeather() {
        ServiceResult serviceResult = weatherService.getWeatherAndSave();
        if (serviceResult != null && serviceResult.isSucceed() && serviceResult.getData() != null) {
            WeatherAO weather = serviceResult.getData();
            //发送数据到webscoket
            messagingTemplate.convertAndSend("/topic/weather", weather);
        }
    }

}

4.vue连接socket,开发环境访问地址:localhost:8089。很明显连接这里出现跨域了。




5.使用filter来解决

   把之前写的跨域类CorsConfig 删除,加入下面的filter。

import org.springframework.stereotype.Component;

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

@Component
public class CorsFilter implements Filter {

    // This is to be replaced with a list of domains allowed to access the server
    //You can include more than one origin here
    private final List allowedOrigins = Arrays.asList("http://localhost:8089");

    public void destroy() {

    }

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "*");
            response.setHeader("Vary", "Origin");

            // Access-Control-Max-Age
            response.setHeader("Access-Control-Max-Age", "3600");

            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");

            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers",
                    "Origin, X-Requested-With, Content-Type, Accept, " + "X-CSRF-TOKEN");
        }

        chain.doFilter(req, res);
    }

    public void init(FilterConfig filterConfig) {
    }
}

加入origin的路径配置: 

vue、springboot集成websocket跨域问题解决_第2张图片

6.测试

vue、springboot集成websocket跨域问题解决_第3张图片

你可能感兴趣的:(websocket)