通过SockJS对STOMP进行安全的WebSocket升级失败,无效升级标头为null

问题描述 投票:6回答:1

我正在使用一个使用Spring Security和WebSockets的Web应用程序。我可以在没有本地机器问题的情况下使用WebSockets,从嵌入式Tomcat的JAR运行Spring Boot应用程序。但是,当我将相同的JAR /项目上载到CloudFoundry或OpenShift(并将其作为可执行JAR运行)时,建立WebSocket连接时的协议升级失败。

我做了一个小示例项目来演示这个问题(至少当我在我的机器或我的CloudFoundry或OpenShift帐户上尝试它时)。它在这里可用:https://github.com/shakuzen/spring-stomp-websocket-test

这是一个简单的,简单的例子,但我能够不断重现这个问题。日志中的错误消息是:

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

默认情况下,DefaultBandshakeHandler的DEBUG日志显示缺少Upgrade标头。但是,如果您查看使用Chrome开发人员工具(或任何浏览器的等效工具)发送的请求,您会看到请求不同。发送了以下两个请求。

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,所以我尝试从控制台运行带有绝对URL的connect命令:

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");
    }
}
spring-security spring-boot stomp sockjs spring-websocket
1个回答
0
投票

问题是OpenShift的端口限制,当时支持websockets。请参阅他们的博客文章https://blog.openshift.com/paas-websockets/,其中提及:

因此,对于普通的WebSockets ws://您将使用端口8000和安全连接wss://端口8443。

当我打开SPR-12371时,来自Spring Framework团队的Rossen发现了这一点。

Stack Overflow上有另一个答案,答案相同:https://stackoverflow.com/a/19952072

© www.soinside.com 2019 - 2024. All rights reserved.