web-dev-qa-db-ja.com

SockJSを使用して異なるドメインに接続するSpring WebSocket

SpringのWebSocketはかなり新しいトピックであり、もう少し探すのが面倒です。

私の問題は、異なるドメインからサービスに接続することです。バックエンドを実行するときに、Linemanとフロントエンド側を構築し、Spring Bootで作業しています。ローカルホストの8080。

「Access-Control-Allow-Origin」ヘッダーに問題がありましたが、許可された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のいずれかに追加情報を追加する必要があるかどうかを考えていましたが、このツールの両方の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();
}
}

また、設定時にOriginAlloweを設定するオプションがあるため、MessageHandlerを設定しようとしましたが、ブローカーにどのように接続されているのかわかりません。

最後に、1つのポートで実行する場合、このセットアップは正しく機能します。

23
Sniady

ジャックスの答えは正しかった:)

RegisterStompEndpointsメソッドを使用すると、許可されたオリジンを設定できます。 「withSockJs()」オプションの前に追加する必要があります。

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

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をトランスポートタイプとして定義しました。

6
Mauro

私の場合、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");
    }
}
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() {

    }
}
1
Fabricelepro