page contents

java webSocket wss踩坑总结教程

本文讲述了Java webSocket wss踩坑总结教程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

attachments-2023-08-R7BxarTt64c9b44968da0.png本文讲述了Java webSocket wss踩坑总结教程!具有很好的参考价值,希望对大家有所帮助。一起跟随六星小编过来看看吧,具体如下:

之前项目中有一套http环境下的webSocket前后台项目(ws协议);

突然测试环境要切换成https,导致webSocket通信遇到了问题(wss协议)。

以下是遇到的问题与解决方法个人总结。

二、问题与解决方法

1.问题概述:vconsole中只报错WebSocket Open Error,但是没有具体错误原因。

问题详情:前端项目是vue移动端app项目,其中有vconsole可以查看debug时控制台打印的信息;

切换为https后,前端代码执行建立webSocket连接的代码时,建立失败,报错WebSocket Open Error(这个错误是自己定义的),但是没有错误原因;

此时后台没有任何日志打印。

解决方法:想办法把app访问的网页url获取到,使用chrome浏览器访问,在F12中,找到了错误信息:

SecurityError: Failed to construct 'WebSocket': An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.

翻译为, 可能无法从通过HTTPS加载的页面启动不安全的WebSocket连接。

终于找到了报错语句,进入下一步。

2.问题描述:An insecure WebSocket connection may not be initiated from a page loaded over HTTPS

问题详情:之前在http环境,前端建立webSocket连接使用的url是没有问题的,样例为:

ws://123.123.123.123:20000/webSocket

而现在,由于是 https环境,因此还使用 ws协议,就会报这个错。

解决方法:把 ws 改为 wss 即可,样例如下:wss://123.123.123.123:20000/webSocket

3.问题描述:修改为wss后,依然无法建立webSocket连接,依然无法从vconsole中找到错误详情;使用chrome进行测试,才发现新的错误信息。

问题详情:新的错误如下:

im.js:1993 WebSocket connection to 'wss://123.123.123.123:20000/webSocket' failed: Error in connection establishment: net::ERR_CERT_COMMON_NAME_INVALID

其中,im.js是前端项目中的一个js文件;

错误信息是:net::ERR_CERT_COMMON_NAME_INVALID

解决方法:这个错误大概意思是说,用一个错误的域名访问了某个节点的https资源(可能是Host错误导致)。

(1)分析发现,chrome打开的前端测试页面的 url为域名形式,样例如下:

https://xxx.xxx.com/result.html

(2)而在这个result.html页面中,引入了im.js文件;在im.js文件中,执行了建立webSocket连接的前端代码;建立连接代码中,访问后台webSocket的 url为IP形式:

wss://123.123.123.123:20000/webSocket

(3)虽然服务器的ip就是123.123.123.123,域名就是xxx.xxx.com,但是由于服务器是https的,https证书中配置的是 *.xxx.com(证书中配置的域名应该是不能自己修改的);

chrome中访问 https://xxx.xxx.com , 会提示连接是 安全 的;

chrome中访问 https://123.123.123.123 , 会提示连接是 不安全 的。

(4)应该是,由于chrome测试时,当前页面url为 https://xxx.xxx.com,因此发送报文的Host参数也为xxx.xxx.com;

而此时发送 wss://123.123.123.123:20000/webSocket 的请求,就会因为Host与请求资源url不一致导致报错(123.123.123.123 != xxx.xxx.com),即使服务器的ip与域名就是123.123.123.123 与xxx.xxx.com也不行。

(5)所以,把 wss 的url从ip改为域名,才解决了 net::ERR_CERT_COMMON_NAME_INVALID 问题。样例如下:

//这个不行

//wss://123.123.123.123:20000/webSocket

//这个可以

wss://xxx.xxx.com:20000/webSocket

三、其它笔记

1.本次服务器 从http变为https 遇到的问题中 (ws变为wss) ,大部分是前端需要修改的;

Java后台WebSocket服务端的代码不需要修改,还是用的ws连接时的代码。(Java后台WebSocket服务端代码不区分ws与wss)

Java后台WebSocket代码主要语句如下:

//这个配置webSocket连接用的url

@ServerEndpoint("/webSocket")

//连接建立,这个方法会被调用

@OnOpen

public void onOpen(WsSession session, EndpointConfig config){//自己写处理逻辑}

//连接关闭,这个方法会被调用

@OnClose

public void onClose(){/*自己写处理逻辑*/}

//前端给后台发来byte数组格式的消息,这个方法会被调用

@OnMessage

public void onMessage(byte[] message){/*自己写处理逻辑*/}

//前端给后台发来String格式的消息,这个方法会被调用

@OnMessage

public void onMessage(String message){/*自己写处理逻辑*/}

//前端给后台发来String格式的消息,这个方法会被调用

@OnError

public void onError(WsSession session, Throwable error){/*自己写处理逻辑*/}

2.从http变为https遇到的问题中(ws变为wss),nginx的配置也不用专门为https修改,使用之前http(ws)时的即可。

nginx可用样例如下:

upstream websocket_cluster {

  server 10.1.2.3:20000;

}


server {

  listen 20000;

  server_name 123.123.123.123;

#因为是测试服务器,虽然是https,但是不用专门配置ssl等参数也可以使用

#ssl on;  

  access_log /home/user/nginx/logs/websocket.log main;

  error_log /home/user/nginx/logs/websocket.error.log;  

  location /webSocket {

    expires -1;

    proxy_set_header Host $http_host;  

    proxxy_pass http://websocket_cluster/webSocket;

    proxy_redirect off;

    proxy_read_timeout 18000;

    proxy_connect_timeout 18000;

    proxy_send_timeout 18000;

    proxy_set_header X-Real-IP $remote_addr;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    client_max_body_size 2g;   

    proxy_http_bersion 1.1;

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection "upgrade";   

  } 

}

说明:

(1)前端访问wss://xxx.xxx.com:20000/webSocket时,dns服务器会把xxx.xxx.com转为123.123.123.123,然后就会访问到这个nginx

(2)根据nginx的配置,20000端口的请求,访问的后缀为/webSocket,可以转发到http://websocket_cluster/webSocket,即http://10.1.2.3:20000/webSocket

(3)Java的WebSocket后台部署在10.1.2.3服务器上,开启的端口是20000,使用了注解@ServerEndpoint("/webSocket"),然后收到前端建立webSocket连接的请求后,@OnOpen注解标注的方法就会被执行了

(4)Java后台后续收到前端发来的消息后,@OnMessage注解标注的方法就会被执行了。

(5)Java后台可以获取到WsSession对象,用来主动给前端发送消息。(这也是webSocket的主要功能,后台主动给前端发消息)

(6)nginx日志中,发现,建立webSocket连接时,日志中并不会打印信息;只有关闭webSocket连接时,日志中才会增加一行记录。

(7)nginx中,webSocket主要的配置就是这两个:

    proxy_set_header Upgrade $http_upgrade;

    proxy_set_header Connection "upgrade";

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。

想高效系统的学习Java编程语言,推荐大家关注一个微信公众号:Java圈子。每天分享行业资讯、技术干货供大家阅读,关注即可免费领取整套Java入门到进阶的学习资料以及教程,感兴趣的小伙伴赶紧行动起来吧。

attachments-2023-03-2AoKIjPQ64014b4ad30a3.jpg

  • 发表于 2023-08-02 09:41
  • 阅读 ( 212 )
  • 分类:Java开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
小柒
小柒

1470 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章