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

WebSockets in Spring — довольно новая тема, и я уже устал искать что-то еще.

Моя проблема заключается в подключении к службе из другого домена, я работаю с Lineman над созданием внешнего интерфейса и Spring Boot при выполнении внутреннего интерфейса, при этом у меня есть эти приложения на двух разных портах: 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(payload); - где полезная нагрузка никогда не определяется. Я пытался, но не смог найти корень вызова, с которого может начинаться.

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

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

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


person Sniady    schedule 28.05.2015    source источник


Ответы (4)


Ответ Джакса был правильным :)

Метод registerStompEndpoints дает нам возможность установить разрешенные источники. Нам нужно добавить его перед опцией withSockJs().

    @Override
    public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
        stompEndpointRegistry.addEndpoint("/BO/socket").setAllowedOrigins("*").withSockJS();
    }
person Sniady    schedule 11.06.2015
comment
Это также соединение с мобильными клиентами, кроме sockjs? - person vthallam; 06.01.2018

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

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

person Mauro    schedule 23.06.2016

В моем случае мне пришлось добавить эти конфигурации, чтобы заставить 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");
    }
}
person Frithjof Schaefer    schedule 12.01.2018
comment
спасибо! Это указало мне правильное направление, я пропустил эту часть в своем приложении :-) - person funder7; 22.05.2020

я нашел это решение, создав фильтр

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

    }
}
person Fabrice Yopa    schedule 12.10.2017
comment
где ты его разместил? Вам нужно было сделать больше изменений, но добавить этот класс? - person TheUnreal; 14.10.2017
comment
я поместил его в папку конфигурации в моем пакете - person Fabrice Yopa; 14.10.2017