Spring WebSocket:由于升级标头无效,握手失败:null

Posted

技术标签:

【中文标题】Spring WebSocket:由于升级标头无效,握手失败:null【英文标题】:Spring WebSocket: Handshake failed due to invalid Upgrade header: null 【发布时间】:2015-09-21 14:19:55 【问题描述】:

我正在使用带有来自后端的 spring 的 wss(安全 Web 套接字)和用于 javascript 客户端的 STOMP。

有谁知道为什么会得到:

Handshake failed due to invalid Upgrade header: null

【问题讨论】:

你能提供更多细节吗?春季版?你的网络配置?你在使用 sockjs 吗?你能复制/粘贴请求和响应标头吗? 供以后参考,当我们遇到“握手失败”这个问题时,我们在后端(JBoss 7.1.6 GA + Spring 5.2.7.RELEASE)也有一个 HTTP 连接泄漏,你可以看到通过在 JBoss CLI 中的 /subsystem=io/worker=default/server=/127.0.0.1:6080 处监视 connection-count。只需应用 http://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html 建议“同时代理 HTTP 和 websockets”,错误日志和泄漏都会消失。 【参考方案1】:

终于找到了解决办法。

我必须在 tomcat 中打开一个 https 端口来处理 wss 请求。

【讨论】:

你是怎么做到的?你能发布解决方案吗?谢谢! 你好,有人能解释一下这个问题吗?我有类似的问题,请指导如何解决。 投反对票。不要告诉我们您找到了解决方案,因为我们不在乎。告诉我们如何找到解决方案。 @MagnoC "我必须在 tomcat 中打开一个 https 端口来处理 wss 请求。" @mspapant 我的服务器已经是纯https(所有http都被重定向)并且没有解决。 WSS 有一个特殊的端口吗?当所有请求都已经是 https 时,我如何open an https port in tomcat for handling wss requests【参考方案2】:

我在使用 nginx https 代理到 tomcat 时遇到了同样的问题。这是因为我不支持 wss 请求。为了支持 wss 请求,我使用如下配置:

# WebSocketSecure SSL Endpoint
#
# The proxy is also an SSL endpoint for WSS and HTTPS connections.
# So the clients can use wss:// connections 
# (e.g. from pages served via HTTPS) which work better with broken 
# proxy servers, etc.

server 
    listen 443;

    # host name to respond to
    server_name ws.example.com;

    # your SSL configuration
    ssl on;
    ssl_certificate /etc/ssl/localcerts/ws.example.com.bundle.crt;
    ssl_certificate_key /etc/ssl/localcerts/ws.example.com.key;

    location / 
        # switch off logging
        access_log off;

        # redirect all HTTP traffic to localhost:8080
        proxy_pass http://localhost:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        # WebSocket support (nginx 1.4)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    

【讨论】:

看起来我也面临同样的问题。这个配置去哪儿了? 我面临同样的问题。但我的网址是 ws://localhost:8070/gs-guide-websocket/518/ufd3l0ca/websocket。我为 ws 请求添加了对端口 8070 的支持。你能帮忙@Jonguo 不好意思我不记得怎么解决了,好久没登陆***了。升级你的 nginx 和 tomcat,也许它可以工作。现在我用的是golang,还没用过tomcat。对不起【参考方案3】:

以下解决方案适合我

<VirtualHost _default_:443>
    
    ServerName my.app
    ServerAdmin admin@my.app
    DocumentRoot /var/www/html
    SSLCertificateFile ...
    SSLCertificateKeyFile ...
    SSLCertificateChainFile ...
    
    ProxyPreserveHost on
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    
    RewriteEngine on
    RewriteCond %HTTP:Upgrade^websocket$ [NC,OR]
    RewriteCond %HTTP:Connection^upgrade$ [NC]
    RewriteRule .* wss:/127.0.0.1:8081%REQUEST_URI [P,QSA,L]
    RewriteCond %REQUEST_URI ^/api/wsendpoint/%var1/%var2/websocket [NC,OR]

    ....
    
</VirtualHost>

希望对你有帮助... 上面的解决方案是以下链接的一部分: https://forum.mattermost.org/t/solved-apache2-reverseproxy-with-websocket-https/437/3

【讨论】:

【参考方案4】:

这篇文章似乎已关闭,但我在这里没有找到确切的解决方案,所以我会发布以备不时之需

我用反向代理配置解决了(在我的例子中是 apache httpd)

首先你必须在 httpd.conf 中启用一些模组

LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule rewrite_module modules/mod_rewrite.so

然后进入您的虚拟主机配置并使用此规则

RewriteCond %HTTP:Upgrade websocket [NC]
RewriteCond %HTTP:Connection upgrade [NC]
RewriteRule /(.*) "ws://[YOUR_URL]:[YOUR_PORT]/$1" [P,L]

如果您使用的是安全网络套接字,显然将 [YOUR_URL] 和 [YOUT_PORT] 替换为真实的 url 和端口,并将“ws”替换为“wss”

就是这样!

如果您在服务器中做了正确的事情,您可以阅读以下标题

upgrade: WebSocket
connection: Upgrade

【讨论】:

以上是关于Spring WebSocket:由于升级标头无效,握手失败:null的主要内容,如果未能解决你的问题,请参考以下文章

Spring WebSocket:握手因升级头无效而失败:null

Gravitee.io websocket 连接

Spring Boot 1.3 WebSocket JSON 转换器产生无效的 JSON

httpd websocket 错误,在“连接”标头中找不到“升级”令牌

做代理时 Nginx 中的 Websocket 升级标头问题

Heroku Node.js WebSocket 服务器错误:“连接”标头值不是“升级”:升级