【问题标题】:Spring WebSocket Connecting with SockJS to a different domainSpring WebSocket 使用 SockJS 连接到不同的域
【发布时间】:2015-08-10 17:56:57
【问题描述】:

Spring 中的 WebSockets 是一个相当新的话题,我很想找到更多。

我的问题是连接到来自不同域的服务,我正在与 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(有效负载); - 从未定义有效负载的地方。我试过但找不到可能开始的调用的根。

我在考虑是否需要在设置连接时向 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,但我不确定它是如何连接到代理的。

最后想想,这个设置在一个端口上运行时可以正常工作。

【问题讨论】:

    标签: spring websocket http-status-code-403 sockjs


    【解决方案1】:

    Jax 的回答是正确的 :)

    registerStompEndpoints 方法让我们有机会设置允许的来源。 我们需要在“withSockJs()”选项之前添加它。

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

    【讨论】:

    • 除了 sockjs 之外,这是否也来自移动客户端的连接?
    【解决方案2】:

    致因尝试通过 SockJsClient 连接到不同域时出现 403 Forbidden 答案而获得此票证的任何人:

    作为握手的一部分,尝试对 /info Url 进行 GET 时会出现问题。响应实际上通过 WGET 和浏览器返回 200。仅通过 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】:

      就我而言,我必须添加这些配置才能让 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");
          }
      }
      

      【讨论】:

      • 谢谢!它为我指明了正确的方向,我在我的应用程序中错过了这部分 :-)
      • 我添加了一个类似上面的类,但它仍然不适合我。
      【解决方案4】:

      我通过创建过滤器找到了这个解决方案

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

      【讨论】:

      • 你把它放在哪里了?您必须进行更多更改但添加此类?
      • 我把它放在我的包的“config”文件夹中
      猜你喜欢
      • 2017-11-20
      • 2020-12-28
      • 2019-08-07
      • 2014-04-24
      • 2015-07-24
      • 2018-09-11
      • 2018-03-21
      • 2021-01-29
      • 2015-01-26
      相关资源
      最近更新 更多