Spring Boot 应用中的 Websocket - 出现 403 Forbidden 错误

36

Spring Boot应用中的Websocket - 获取403 Forbidden错误

当我在eclipse中运行时(没有使用Spring Boot),我可以使用sockjs/stompjs从客户端连接到Websocket。

但是,当我为Websocket代码创建了一个Spring Boot jar(gradlew build),并运行java -jar websocket-code.jar时,我会得到一个403错误来连接Websocket。

我对Websocket没有进行身份验证。 我有一个CORS过滤器,并认为在请求/响应中所有头都正确。

以下是我的build.gradle文件

apply plugin: 'java'
apply plugin: 'spring-boot'
apply plugin: 'war'

sourceCompatibility = 1.7
version = '1.0'

repositories {
    mavenCentral()
}

buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.5.RELEASE")
    }
}

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    compile "org.springframework:spring-web:$spring_version"
    compile "org.springframework:spring-webmvc:$spring_version"
    compile "org.springframework:spring-websocket:$spring_version"
    compile "org.springframework:spring-messaging:$spring_version"
    compile "org.springframework.boot:spring-boot-starter-websocket"
    compile "org.springframework.boot:spring-boot-starter-web"
    compile "com.fasterxml.jackson.core:jackson-databind:2.6.2"
    compile "com.fasterxml.jackson.core:jackson-core:2.6.2"
    compile "com.fasterxml.jackson.core:jackson-annotations:2.6.2"
    compile "org.springframework.amqp:spring-rabbit:1.3.5.RELEASE"
    compile("org.springframework:spring-tx")
    compile("org.springframework.boot:spring-boot-starter-web:1.2.6.RELEASE")
    compile("org.springframework.boot:spring-boot-starter-jetty:1.2.6.RELEASE")
    testCompile group: 'junit', name: 'junit', version: '4.11'
    testCompile "org.springframework:spring-test:$spring_version"
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.5'
}

更新:

添加了一个CORS过滤器,使用response.setHeader("Access-Control-Allow-Origin", "http://localhost:8089");

在客户端firebug中。

Request Headers 
Origin  
http://localhost:8089

Response Headers
Access-Control-Allow-Origin
http://localhost:8089

Server Logs
2015-10-02 16:57:31.372 DEBUG 1848 --- [qtp374030679-14] o.s.w.s.s.t.h.DefaultSockJsService       : Request rejected, Origin header value http://localhost:8089 not allowed

我请求的来源在允许来源列表中。但是日志中仍然会收到“请求被拒绝”的消息。

4个回答

93

我曾遇到类似的问题,并通过设置WebSocketConfig的允许来源为“*”来解决它。

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // the endpoint for websocket connections
        registry.addEndpoint("/stomp").setAllowedOrigins("*").withSockJS();
    }

    // remaining config not shown as not relevant
}

2
谢谢你的回答。我认为在新版本中,setAllowedOrigins已经被添加到了StompWebSocketEndpointRegistration中。我想你的解决方案应该在新版本中有效。我正在使用较旧的websocket jar。 - user3755282
9
使用通配符作为allowedOrigins是否不安全? - niilzon
谢谢,我的最初想法是在WebMvcConfigurerAdapter中设置CORS的允许来源。这个方法确实行得通! - Ryan Pelletier
1
@niilzon,这取决于操作目的。一般来说,我更倾向于同意你的观点。但是你可以简单地将通配符与特定主机进行交换,例如 setAllowedOrigins("http://somehost")。这可能看起来很清晰,但当我在这篇文章上遇到困难时,我还是有必要说一下它 :-) - Fencer
我们在哪里可以找到这个文件? - Bilal Ahmed Yaseen
4
请注意,这个方法同样适用于在WebSocketConfigurer中注册的原始网络套接字。在public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) 方法中,您可以调用 registry.addHandler(new MyWebSocketHandler(), "/some-path").setAllowedOrigins("*")。不幸的是,WebSocket无法告诉您它是一个CORS问题……403错误会让人误解。 - user5365075

5

尝试添加

registry.addEndpoint("/your-end-point").setAllowedOrigins("*").withSockJS();

我猜测您提到的“your-end-point”在控制器中是由@SendTo注册的。

4
我的两个环境之间的差异是JAR包的版本。
spring-boot-starter-websocket-1.2.5.RELEASE.jar
spring-websocket-4.1.7.RELEASE.jar

由于使用了spring-boot-starter-websocket的依赖,打包时它会选择spring-websocket-4.1.7.RELEASE版本,而不是spring_version=4.0.6.RELEASE版本。

在build.gradle文件中修改了依赖项,问题得到解决。

compile "org.springframework.boot:spring-boot-starter-websocket:1.1.0.RELEASE"

我认为在最新版的spring-websocket jar中,类StompWebSocketEndpointRegistration有一个setAllowedOrigins方法需要使用。我尚未尝试过这种方法。
但是CORS过滤器通过
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8089");

正在使用旧版本。

不确定这些是否仍然有效。对我来说,它说Web套接字层需要凭据为真,即使我在CORS中设置了我的允许来源。我仍然收到403禁止访问的错误。 - numerical25
在Spring Boot MVN中,我只是更新了相同的版本,它就可以工作了:https://www.stackextend.com/angular/websocket-with-spring-boot-and-angular/ 版本号:2.0.7.RELEASE - nobjta_9x_tq

3

参考资料,较新版本的Spring需要使用不同的方法:

registry.addEndpoint("/websocket-connection").setAllowedOriginPatterns("*").withSockJS();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接