Spring WebSocket与SockJS连接到不同的域

时间:2015-05-28 09:45:57

标签: spring websocket http-status-code-403 sockjs

Spring中的WebSockets是一个相当新的话题,我很难找到更多。

我的问题是连接到来自不同域的服务,我正在使用Lineman构建前端端和Spring Boot做后端端,我在两个不同的端口上有这些应用程序:localhost上的8000和8080。

我遇到了'Access-Control-Allow-Origin'标题的问题,但是我已经通过在服务器端添加一个过滤器来解决它,该过滤器将允许的原点添加到标头中。在此之后,我开始在连接上收到以下错误:

GET http://localhost:8080/socket/info 403 (Forbidden)
AbstractXHRObject._start @ sockjs-0.3.4.js:807
(anonymous function) @sockjs-0.3.4.js:841

我在项目中没有Spring Security,所以这不是授权问题,错误指向sockJS: that.xhr.send(有效载荷); - 从未定义有效负载。我尝试过但无法找到可能开始的呼叫根。

我在考虑在设置连接时是否需要向SockJS和Stomp添加一些其他信息,但这些工具的两个wiki页面中没有太多的示例和注释。

Bellow你会发现连接JS代码。

var socket = new SockJS("http://localhost:8080/socket");
client = Stomp.over(socket);

client.connect({'login': BoatsGame.userName,
                    'passcode': 'guest'},
            function (frame) {
....

The Server Side has a MessageBroker configured :    


@Configuration
@EnableWebSocketMessageBroker
public class MessageBrokerConfig extends AbstractWebSocketMessageBrokerConfigurer {

@Bean
public ServletServerContainerFactoryBean createWebSocketContainer() {
     ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
     container.setMaxTextMessageBufferSize(8192);
     container.setMaxBinaryMessageBufferSize(8192);
     return container;
}

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
     //config.enableStompBrokerRelay("/queue", "/topic");
     config.enableSimpleBroker("/queue", "/topic","/user");
     config.setApplicationDestinationPrefixes("/BoatBattleGame");
}

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

我还尝试设置MessageHandler,因为它可以在配置时设置OriginAllowe,但我不确定它是如何连接到代理的。

最后想一想,在一个端口上运行时,此设置可正常工作。

4 个答案:

答案 0 :(得分:52)

Jax的anwesr是正确的:)

registerStompEndpoints方法让我们有机会设置允许的起源。 我们需要在“withSockJs()”选项之前添加它。

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

答案 1 :(得分:6)

在尝试通过SockJsClient连接到其他域时,由于403 Forbidden答案而获得此票证的任何人:

在尝试对/ info Url进行GET时会出现问题,这是握手的一部分。响应实际上通过WGET以及浏览器返回200。只有通过SockJsClient它才能工作。

尝试不同的解决方案后,唯一真正解决问题的方法是编写一个实现Transport和InfoReceiver的类。通过这种方式,开发人员可以直接处理握手的这一部分。 基本上你在executeInfoRequest()方法中完成工作:

@Override
public String executeInfoRequest(URI infoUrl, HttpHeaders headers) {
    HttpGet getRequest = new HttpGet(infoUrl); // eventually add headers here
    HttpClient client = HttpClients.createDefault();

    try {
        HttpResponse response = client.execute(getRequest);
        List<String> responseOutput = IOUtils.readLines(response.getEntity().getContent());

        return responseOutput.get(0);
    } catch (IOException ioe) {
        ...
    }
}

我将TransportType.XHR定义为传输类型。

答案 2 :(得分:2)

就我而言,我必须添加这些配置以使SockJS / STOM与CORS一起使用:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer
{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowCredentials(false)
                .maxAge(3600)
                .allowedHeaders("Accept", "Content-Type", "Origin", 
"Authorization", "X-Auth-Token")
                .exposedHeaders("X-Auth-Token", "Authorization")
                .allowedMethods("POST", "GET", "DELETE", "PUT", "OPTIONS");
    }
}

答案 3 :(得分:1)

i found this solution by creating a Filter

package com.diool.notif.config;

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 {

    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SimpleCORSFilter.class);
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        LOGGER.info("Initilisation du 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() {

    }
}