Spring WebSocket Подключение с SockJS к другому домену

WebSockets в Spring - довольно новая тема, в которой я найду немного больше.

Моя проблема заключается в подключении к сервису из другого домена, я работаю с Lineman, создающим интерфейсную часть и Spring Boot, когда делаю заднюю часть, с этим я имею эти приложения на двух разные порты: 8000 и 8080 на localhost.

У меня были проблемы с заголовком "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 Безопасность в проекте, так что это не проблема авторизации, ошибка указывает на sockJS: that.xhr.send(полезная нагрузка); - где полезная нагрузка никогда не определена. Я попытался, но не смог найти корень вызова, где может начаться.

Я думал, если мне нужно добавить дополнительную информацию к SockJS и Stomp при настройке соединения, но на обеих страницах wiki этих инструментов не так много примеров и заметок.

Ниже вы найдете код подключения 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 при настройке, но я не уверен, как он связан с брокером.

Подумайте, эта настройка работает правильно при работе на одном порту.

Ответы

Ответ 1

Jax anwesr был прав:

Метод registerStompEndpoints дает нам возможность установить Allowed Origins. Нам нужно добавить его перед опцией "withSockJs()".

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

Ответ 2

К кому угодно добраться до этого билета из-за запрещенного ответа 403 при попытке подключиться через SockJsClient к другому домену:

Проблема возникает при попытке сделать GET в /info Url, как часть подтверждения. Ответ фактически возвращает 200 через WGET, а также через браузер. Только через 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 как тип транспорта.

Ответ 3

Я нашел это решение, покупая создание фильтра

    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() {

    }
}

Ответ 4

В моем случае мне пришлось добавить эти конфигурации, чтобы заставить 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");
    }
}