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");
}
}