wss连接的一些坑

一、内容

浏览器控制面板异常信息

Mixed Content: The page at ‘https://{域名}.com/‘ was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint ‘ws://{ip}:{port}/‘. This request has been blocked; this endpoint must be available over WSS.
Uncaught DOMException: Failed to construct ‘WebSocket’: An insecure WebSocket connection may not be initiated from a page loaded over HTTPS.

  • 好家伙,这种情况,毫无疑问我们就需要使用 wss:// 安全协议了,于是立即联系h5客户端,把连接服务端webscoket的形式由ws:// 改为 wss:// 。本以为这样就解决了,没想到一段时间后下一个问题又来了。

扩展:关于 ws 和 wss

WebSocket可以使用 ws 或 wss 来作为统一资源标志符,类似于 HTTP 或 HTTPS。其中 ,wss 表示在 TLS 之上的 WebSocket,相当于 HTTPS。默认情况下,WebSocket的 ws 协议基于Http的 80 端口;当运行在TLS之上时,wss 协议默认是基于Http的 443 端口。说白了,wss 就是 ws 基于 SSL 的安全传输,与 HTTPS 一样样的道理。所以,如果你的网站是 HTTPS 协议的,那你就不能使用 ws:// 了,浏览器会 block 掉连接,和 HTTPS 下不允许 HTTP 请求一样。

  • h5客户端改成wss连接后,测试发现还是无法正常游戏。无奈,再次打开浏览器面板,果然,又看到一个新的问题。

浏览器控制面板异常信息

WebSocket connection to ‘wss://{ip}:{port}/‘ failed: Error in connection establishment: net::ERR_SSL_PROTOCOL_ERROR

  • 之前在Http的情况下,客户端一直是用ip+port的形式来连接服务端,当然了也不会出现什么问题。很明显,在更改成Https后,若还是以这种方式连接服务端,浏览器就会报 SSL 协议错误,这很明显就是证书的问题。如果这时候还用 IP + 端口号 的方式连接 WebSocket ,是根本就没有证书存在的(即使我们在Nginx配置了SSL证书,但这种方式其实是不会走Nginx代理的),所以在生成环境下,更推荐大家用域名的方式来连接。于是,立刻又联系前端,再一次做更改,修改为 wss://{域名}/ 进行连接。我以为这样就真的解决了,没想到还是too young too simple,没一会下个问题又来了,测试反馈的结果还是不可以,第三次打开浏览器控制面板,果然又是一个新的错误信息。

浏览器控制面板异常信息

WebSocket connection to ‘wss://{域名}/‘ failed: Error during WebSocket handshake: Unexpected response code: 400

  • 看到这个错误信息后,确定这是服务端返回的400响应。既然可以请求到服务端,就说明客户端这边是没有问题的,那么问题最可能出在客户端和服务端之间。由于中间层使用了Nginx做转发,所以导致服务端无法知道这是一个合法的WebSocket请求。于是立刻查找了网上资料,在Nginx配置文件加入了以下配置,成功解决了这个问题。
server {
    location / {
            proxy_pass http://localhost:{port};
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
    }
}
  • 接着,连忙拿域名进行再次连接测试,终于看到了101 Switching Protocols的响应Status Code。就这样,也算是终于解决完在 HTTPS 下以 wss://{域名}/ 的方式连接 WebSocket的一系列问题。不过,最后这其中还有一个小问(插)题(曲)。

关于Nginx中的WebSocket配置

自1.3 版本开始,Nginx就支持 WebSocket,并且可以为 WebSocket 应用程序做反向代理和负载均衡。WebSocket 和 HTTP 是两种不同的协议,但是 WebSocket 中的握手和 HTTP 中的握手兼容,它使用 HTTP 中的 Upgrade 协议头将连接从 HTTP 升级到 WebSocket,当客户端发过来一个 Connection: Upgrade请求头时,其实Nginx是不知道的。所以,当 Nginx 代理服务器拦截到一个客户端发来的 Upgrade 请求时,需要我们显式的配置Connection、Upgrade头信息,并使用 101(交换协议)返回响应,在客户端、代理服务器和后端应用服务之间建立隧道来支持 WebSocket。
   当然,还需要注意一点,此时WebSocket 仍然受到 Nginx 缺省为60秒的 proxy_read_timeout 配置影响。这意味着,如果你有一个程序使用了 WebSocket,但又可能超过60秒不发送任何数据的话,那么需要增大超时时间(配置proxy_read_timeout),要么实现一个Ping、Pong的心跳消息以保持客户端和服务端的联系。使用Ping、Pong的解决方法有额外的好处,如:可以发现连接是否被意外关闭等。

  • 关于最后的这个小问题,主要是在对Nginx配置的时候将location=/的请求都进行了proxy_pass(转发)。由于h5客户端的文件打包成静态文件后,存放在服务器的指定目录下(这里假设在/root/html/static/路径下),这也就导致这种配置的情况下Nginx无法正常代理指定目录下的客户端文件。于是再一次修改配置文件,添加location配置,最终完美解决所有问题。
location /static/ {
    root /root/html;
}

二、相关地址

Spring Boot是一个非常流行的Java Web框架,它提供了一种简单的方式来构建现代Web应用程序。Spring Boot支持用WebSocket在客户端和服务器之间提供实时交互的功能。也就是说,Spring Boot和WebSocket在业务场景中的应用非常广泛。此外,如果需要安全加密的连接,可以使用WebSocket over SSL (wss)协议。 下面介绍一下如何在Spring Boot中配置wss连接: 1. 配置证书 在Spring Boot中,要使用wss连接,必须启用SSL,并配置证书。自己生成的证书可以使用Java Keytool命令生成,也可以使用商业证书。需要将证书保存到Spring Boot工程的某个路径中。 2. 配置Tomcat Spring Boot使用的默认Web容器是Tomcat,要开启wss连接需要在application.properties文件中添加如下配置: ``` server.port=8443 server.ssl.key-store=classpath:/keystore/yourKeyStore.jks server.ssl.key-store-password=yourPassword server.ssl.key-password=yourPassword server.ssl.keyAlias=yourKeyAlias ``` 这里server.port是SSL协议默认端口,server.ssl.key-store为证书的路径和名称,server.ssl.key-store-password和server.ssl.key-password为证书的密码,server.ssl.keyAlias为证书的别名。 3. 添加支持WebSocket的依赖包 在Spring Boot工程的maven项目中,需要添加如下的依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 4. 编写WebSocket处理类 在Spring Boot中需要有一个WebSocket处理类来处理与客户端的交互。示例代码如下: ``` @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").setAllowedOrigins("*").withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); config.setApplicationDestinationPrefixes("/app"); } } ``` 这里使用了Spring的两个注解@Configuration和@EnableWebSocketMessageBroker。registerStompEndpoints方法是为了建立WebSocket连接,并且允许跨域访问。configureMessageBroker方法的作用是配置消息代理和目的头前缀。 5. 在控制器中使用WebSocket 在具体的控制器中,可以使用sendMessage方法来向客户端发送消息,如下所示: ``` @Autowired private SimpMessagingTemplate messagingTemplate; ... @GetMapping("/test") public void sendMessage() { messagingTemplate.convertAndSend("topic/test", "Hello World!"); } ``` 这里@Autowired是注入SimpMessagingTemplate,sendMessage方法是将消息发布到指定的主题中。 通过以上这些步骤,就可以在Spring Boot中完成wss连接的构建。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值