Spring WebSocket 使用 SockJS 连接到不同的域
Spring WebSocket Connecting with SockJS to a different domain
Spring 中的 WebSockets 是一个相当新的主题,我很难找到更多内容。
我的问题是连接到来自不同域的服务,我正在与 Lineman 一起构建 front-end 端,Spring 在 back-end 端进行引导,因此,我在两个不同的端口上安装了这些应用程序:localhost 上的 8000 和 8080。
我在使用 'Access-Control-Allow-Origin' header 时遇到了问题,但我已经通过在服务器端添加一个过滤器来解决它,该过滤器将允许的来源添加到 header。在此之后,我开始在连接时遇到以下错误:
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(有效载荷); - 有效负载从未 defined.I 尝试过,但找不到可能开始的调用的根。
我在考虑是否需要在设置连接时向 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,但我不确定它是如何连接到代理的。
最后想想,当 运行 在一个端口上时,此设置可以正常工作。
Jax 的回答是正确的:)
registerStompEndpoints 方法让我们有机会设置允许的来源。
我们需要在 "withSockJs()" 选项之前添加它。
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/BO/socket").setAllowedOrigins("*").withSockJS();
}
对于在尝试通过 SockJsClient 连接到不同域时因 403 禁止回答而获得此票证的任何人:
作为握手的一部分,尝试对 /info Url 进行 GET 时出现问题。响应实际上 returns 通过 WGET 和浏览器返回 200。仅通过 SockJsClient 无效。
在尝试了不同的解决方案之后,唯一真正解决问题的方法是编写一个 class 来实现传输和 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 定义为传输类型。
我通过创建过滤器找到了这个解决方案
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() {
}
}
就我而言,我必须添加这些配置才能让 SockJS/STOMP 与 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");
}
}
Spring 中的 WebSockets 是一个相当新的主题,我很难找到更多内容。
我的问题是连接到来自不同域的服务,我正在与 Lineman 一起构建 front-end 端,Spring 在 back-end 端进行引导,因此,我在两个不同的端口上安装了这些应用程序:localhost 上的 8000 和 8080。
我在使用 'Access-Control-Allow-Origin' header 时遇到了问题,但我已经通过在服务器端添加一个过滤器来解决它,该过滤器将允许的来源添加到 header。在此之后,我开始在连接时遇到以下错误:
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(有效载荷); - 有效负载从未 defined.I 尝试过,但找不到可能开始的调用的根。
我在考虑是否需要在设置连接时向 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,但我不确定它是如何连接到代理的。
最后想想,当 运行 在一个端口上时,此设置可以正常工作。
Jax 的回答是正确的:)
registerStompEndpoints 方法让我们有机会设置允许的来源。 我们需要在 "withSockJs()" 选项之前添加它。
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/BO/socket").setAllowedOrigins("*").withSockJS();
}
对于在尝试通过 SockJsClient 连接到不同域时因 403 禁止回答而获得此票证的任何人:
作为握手的一部分,尝试对 /info Url 进行 GET 时出现问题。响应实际上 returns 通过 WGET 和浏览器返回 200。仅通过 SockJsClient 无效。
在尝试了不同的解决方案之后,唯一真正解决问题的方法是编写一个 class 来实现传输和 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 定义为传输类型。
我通过创建过滤器找到了这个解决方案
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() {
}
}
就我而言,我必须添加这些配置才能让 SockJS/STOMP 与 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");
}
}