Secure WebSocket update via STOMP via SockJS failed with invalid null update header

I am working on a web application that uses Spring Security and WebSockets. I can use WebSockets without problems from my local machine by running the Spring boot application from the JAR with Tomcat built-in. However, when I load the same JAR / project into CloudFoundry or OpenShift (and run it as an executable JAR), updating the protocol while establishing a connection to WebSocket fails.

I made a small sample project that demonstrates this problem (at least when I try to use it on my machine or my CloudFoundry or OpenShift account). It is available here: https://github.com/shakuzen/spring-stomp-websocket-test

This is an example of a trimmed, bare bone, but I can consistently recreate the problem. Error message in logs:

2014-10-20T00:46:36.69+0900 [App/0]   OUT 2014-10-19 15:46:36.698 DEBUG 32 --- [io-61088-exec-5] o.s.w.s.s.s.DefaultHandshakeHandler      : Invalid Upgrade header null

The DEBUG log for DefaultHandshakeHandler previously shows that the Upgrade header is missing. However, if you look at the request sent using the Chrome developer tools (or any other equivalent browser tool), you will see that the request is different. The following two requests were sent.

1

GET /hello/info HTTP/1.1
Host: sswss-test.cfapps.io
Connection: keep-alive
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
Accept: */*
Referer: http://sswss-test.cfapps.io/message
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,ja;q=0.6
Cookie: __VCAP_ID__=693dd6ff1b494f88a2c8567590da500dc44b4818746a45b28dd98a29b2607395; JSESSIONID=C5485065FE0A1DBCDF1F148A63D08FC2
DNT: 1

2

GET ws://sswss-test.cfapps.io/hello/863/olm1kojs/websocket HTTP/1.1
Host: sswss-test.cfapps.io
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Authorization: Basic dGVzdHVzZXI6dGVzdHBhc3M=
Upgrade: websocket
Origin: http://sswss-test.cfapps.io
Sec-WebSocket-Version: 13
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.104 Safari/537.36
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,ja;q=0.6
Cookie: __VCAP_ID__=693dd6ff1b494f88a2c8567590da500dc44b4818746a45b28dd98a29b2607395; JSESSIONID=C5485065FE0A1DBCDF1F148A63D08FC2
Sec-WebSocket-Key: 7bW1pg6f9axkVfqV21k/9w==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

, - . , (, localhost sswss-test.cf.apps.io ) , , . Chrome Firefox.

GitHub, , Spring Boot 1.2.0.M2, (1.1.8.RELEASE) . , , , SockJS URL- , , connect URL-:

var socket2 = new SockJS('http://sswss-test.cfapps.io/hello');

, , .

. GitHub ( OpenShift , , ). .

WebSocketConfig

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

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

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello").withSockJS();
    }
}

SecurityConfig

Facebook , , .

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic()
            .and()
            //Configures url based authorization
            .authorizeRequests()
                // Anyone can access the urls
                .antMatchers("/").permitAll()
                //The rest of the our application is protected.
                .antMatchers("/**").authenticated();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("testuser").password("testpass").roles("USER").and()
                .withUser("adminuser").password("adminpass").roles("ADMIN","USER");
    }
}
+4

All Articles