Search code examples
spring-securityspring-websocketspring-session

Spring SockJs RequestHandler doesn't upgrade connection to 101


Even though this is not described in the Spring documentation, a websocket connect should lead to a connection upgrade response (101 status).

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig<S extends ExpiringSession> extends AbstractSessionWebSocketMessageBrokerConfigurer<S>{

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic", "/queue");

        config.setApplicationDestinationPrefixes("/mobile-server");

        config.setUserDestinationPrefix("/mobile-user");

    }

    @Override
    public void configureStompEndpoints(StompEndpointRegistry registry) {
        registry
            .addEndpoint("/ws")
            .setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
            .setAllowedOrigins("*")
            .withSockJS()
            .setSessionCookieNeeded(false)
            ;
    }

}

However, I get a 200 status with a "Welcome to SockJS" message which is generated by TransportHandlingSockJsService in stead of the WebSocketHttpRequestHandler which would generate the upgrade AFAIK

@Configuration
public class WebSocketSecurity extends AbstractSecurityWebSocketMessageBrokerConfigurer{

 @Override
 protected boolean sameOriginDisabled() {
    return true;
 }

    @Override
 protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
      messages
        .nullDestMatcher().permitAll()
        .simpSubscribeDestMatchers("/user/queue/errors").permitAll()
        .simpDestMatchers("/mobile-server/**").hasRole("ENDUSER")
        .simpSubscribeDestMatchers("/user/**", "/topic/**").hasRole("ENDUSER")
        .anyMessage().denyAll();
  }
}

When I change the config to

@Override
public void configureStompEndpoints(StompEndpointRegistry registry) {
    registry
        .addEndpoint("/ws")
        .setHandshakeHandler(new DefaultHandshakeHandler(new TomcatRequestUpgradeStrategy()))
        .setAllowedOrigins("*");
}

to my surprise a call to /ws does lead to a connection upgrade 101. I'm surprised, since the documentation and all examples uniformly use the withSockJS() and the start of any websocket connection AFAIK is a request upgrade.

I can choose to force the upgrade by connecting to /ws/websocket (also not documented). So, I'm not sure what is best.

Any suggestions?


Solution

  • This is expected behavior. It's how the SockJS protocol works: http://sockjs.github.io/sockjs-protocol/sockjs-protocol-0.3.3.html. There is an initial "greeting" request and then the client starts trying transports one at a time.