Spring WebSocket 与 SockJS 连接到不同的域
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30502943/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Spring WebSocket Connecting with SockJS to a different domain
提问by Sniady
WebSockets in Spring is a rather new topic that I;m tiring to find a bit more.
Spring 中的 WebSockets 是一个相当新的话题,我很累,想找到更多。
My problem is with connecting to a service from a different domain, I'm working on with Lineman building the front-end side and Spring Boot when doing the back-end side, with that I have these apps on two different ports : 8000 and 8080 on localhost.
我的问题是连接到来自不同域的服务,我正在与 Lineman 一起构建前端端和 Spring Boot 在后端端,我在两个不同的端口上安装了这些应用程序:8000 和本地主机上的 8080。
I had issues with the 'Access-Control-Allow-Origin' header but I have resolved it by adding a filter on the server side which added the allowed origin to the header. After this I started to get the following error on connection:
我遇到了“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
I don't have Spring Security in the project so this is not an authorization issue, the error points to sockJS : that.xhr.send(payload); - where payload is never defined.I tried but couldn't find the root of the call where is may began.
我在项目中没有 Spring Security 所以这不是授权问题,错误指向 sockJS : that.xhr.send(payload); - 从未定义有效载荷的地方。我尝试过但找不到可能开始的调用的根。
I was thinking if I need to add some additional information to either SockJS and Stomp when setting the connection, but there is not much of examples and notes in both wiki pages of this tools.
我在想是否需要在设置连接时向 SockJS 和 Stomp 添加一些附加信息,但是在此工具的两个 wiki 页面中都没有太多示例和注释。
Bellow you will find the connection JS code.
波纹管你会发现连接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();
}
}
I Also tried setting up a MessageHandler as it has the option to set OriginAllowe when configuring, but I'm not sure how it is connected to the broker.
我还尝试设置 MessageHandler,因为它可以在配置时选择设置 OriginAllowe,但我不确定它是如何连接到代理的。
Last think, this setup works correctly when running on one port.
最后想一想,这个设置在一个端口上运行时可以正常工作。
回答by Sniady
Jax's anwesr was correct :)
Jax 的回答是正确的 :)
The registerStompEndpoints method gives us the opportunity to set the Allowed Origins. We need to add it before the "withSockJs()" option.
registerStompEndpoints 方法让我们有机会设置 Allowed Origins。我们需要在“withSockJs()”选项之前添加它。
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/BO/socket").setAllowedOrigins("*").withSockJS();
}
回答by Mauro
To anyone getting to this ticket because of the 403 Forbidden answer when trying to connect through a SockJsClient to a different domain:
对于尝试通过 SockJsClient 连接到不同域时由于 403 Forbidden 答案而获得此票证的任何人:
The problem arises when trying to make a GET to the /info Url, as part of the handshaking. The response actually returns a 200 via WGET as well as via browser. Only through SockJsClient it doesn't work.
作为握手的一部分,尝试对 /info Url 进行 GET 时会出现问题。响应实际上通过 WGET 以及浏览器返回 200。只有通过 SockJsClient 它不起作用。
After trying different solutions, the only one that really fixed the issue is to write a class that implements Transport and InfoReceiver. In this way the developer can directly handle this part of the handshake. Basically you make the work in the executeInfoRequest() method:
在尝试了不同的解决方案后,唯一真正解决问题的方法是编写一个实现 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) {
...
}
}
I defined TransportType.XHR as transport type.
我将 TransportType.XHR 定义为传输类型。
回答by Frithjof Schaefer
In my case, I had to add these configuarations to get SockJS / STOM to work with CORS:
就我而言,我必须添加这些配置才能让 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");
}
}
回答by Fabrice Yopa
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() {
}
}