服务器中使用wss协议连接websocket(基于netty)

ops/2024/10/22 21:29:14/

前置条件:可用的SSL证书

需要两个文件,key格式的还有pem格式的

如果是阿里云证书,下面Nginx类型的就可以

快捷转移——数字证书管理服务管理控制台 (aliyun.com)

在这里插入图片描述

自建证书

以管理员形式打开cmd窗口,如果提示keytool不存在,将目录定位到java安装目录的bin下方。

1、生成证书

keytool -genkey -alias myalias -keyalg RSA -keysize 2048 -keystore mykeystore.jks -validity 365

2、jks证书转化为pem格式

keytool -export -alias myalias -keystore mykeystore.jks -rfc -file certificate.pem

3、导出私钥

keytool -importkeystore -srckeystore mykeystore.jks -destkeystore temp.p12 -srcalias myalias -deststoretype PKCS12 -srcstorepass <keystore_password> -deststorepass <p12_password>

4、提取私钥

openssl pkcs12 -in temp.p12 -nocerts -nodes -out private_key.pem

这种方式得到两个接下来要用到的文件

① certificate.pem

② private_key.pem

阿里云证书的方式直接下载得到的是key和pem,需要将key转化为私钥

执行openssl rsa -in old_server_key.pem -out private_key.pem

这样也得到了上述两个文件

接下来使用netty搭建简易websocket服务器

@Configuration
@Slf4j
public class NettyWebSocketServer {private final static int WEB_SOCKET_PORT = 9090;private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);private final EventLoopGroup workerGroup = new NioEventLoopGroup(NettyRuntime.availableProcessors());@PostConstructpublic void start() throws Exception {run();}@PreDestroypublic void destroy() {Future<?> future = bossGroup.shutdownGracefully();Future<?> future1 = workerGroup.shutdownGracefully();future.syncUninterruptibly();future1.syncUninterruptibly();log.info("关闭 ws server 成功");}public void run() throws Exception {ServerBootstrap serverBootstrap = new ServerBootstrap();SslContext sslContext = SslContextBuilder.forServer(getCertPem(), getCertKey()).build();serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128).option(ChannelOption.SO_KEEPALIVE, true).handler(new LoggingHandler(LogLevel.INFO)) // 为 bossGroup 添加 日志处理器.childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();// 注意将SSL必须是第一个处理器pipeline.addLast(sslContext.newHandler(socketChannel.alloc()));//30秒客户端没有向服务器发送心跳则关闭连接pipeline.addLast(new IdleStateHandler(30, 0, 0));// 因为使用http协议,所以需要使用http的编码器,解码器pipeline.addLast(new HttpServerCodec());// 以块方式写,添加 chunkedWriter 处理器pipeline.addLast(new ChunkedWriteHandler());/*** 说明:*  1. http数据在传输过程中是分段的,HttpObjectAggregator可以把多个段聚合起来;*  2. 这就是为什么当浏览器发送大量数据时,就会发出多次 http请求的原因*/pipeline.addLast(new HttpObjectAggregator(8192));//保存用户ippipeline.addLast(new HttpHeadersHandler());/*** */pipeline.addLast(new WebSocketServerProtocolHandler("/"));}});// 启动服务器,监听端口,阻塞直到启动成功serverBootstrap.bind(WEB_SOCKET_PORT).sync();log.info("netty在{}启动成功", WEB_SOCKET_PORT);}private InputStream getCertPem() {ClassPathResource classPathResource = new ClassPathResource("certificate.pem");return classPathResource.getStream();}private InputStream getCertKey() {ClassPathResource classPathResource = new ClassPathResource("private_key.pem");return classPathResource.getStream();}}

然后加成jar包放到服务器上启动。

配置nginx反向代理

server{listen 443 ssl;server_name your-server-name; # 填写①ssl_certificate certificate.pem; # 填写路径②ssl_certificate_key private_key.pem; # 填好路径③ssl_session_timeout 5m;root /www/wwwroot; # 自行配置charset utf-8;location /netty{proxy_pass https://your-address-url:9090/; # 填写④ 不能是9090 必须是9090/proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "Upgrade";rewrite "^/netty/(.*)$" /$1 break;}
}

测试 wss://your-server-name/netty 可以连接成功

常见错误

1、io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record

错误说明没有使用SSL/TLS

导致的原因可能是:

① 使用了ws协议连接

② nginx转发的时候使用了http,需要使用https

2、wss Received fatal alert: certificate_unknown

错误说明证书未知

导致的原因可能是:

① 证书错误、不被信任


http://www.ppmy.cn/ops/127662.html

相关文章

three.js 使用geojson ,实现中国地图区域,边缘流动效果

three.js 使用geojson &#xff0c;实现中国地图区域&#xff0c;边缘流动效果 在线链接&#xff1a;https://threehub.cn/#/codeMirror?navigationThreeJS&classifyexpand&idgeoBorder 国内站点预览&#xff1a;http://threehub.cn github地址: https://github.co…

Golang文件操作:读取与写入全攻略

文章目录 1. 文件操作基础2. 文件的打开和创建2.1 打开文件2.2 创建文件 3. 文件写入操作3.1 使用os.File.WriteString写入字符串3.2 使用bufio进行缓冲写入 4. 文件读取操作4.1 按行读取文件4.2 一次性读取整个文件 5. 文件权限与打开模式详解5.1 使用os.OpenFile设置文件打开…

【接口限流】java中springboot实现接口限流防抖处理(JUC注解版)

文章目录 1、添加pom项目依赖2、注解类RateLimit3、限流切面RateLimitAspect4、controller层使用注解小结 1、添加pom项目依赖 <!--AspectJ来实现切面&#xff0c;在方法执行前进行限流检查--><dependency><groupId>org.aspectj</groupId><artifact…

学习第三十六行

QValidator::State里面state为0&#xff0c;完全不匹配&#xff0c;1&#xff0c;部分匹配&#xff0c;2&#xff0c;完全匹配,对于label或者textedit里面的字符均为QString类型&#xff0c;特别是遇到数字&#xff0c;需要QString::number转化&#xff0c;对于正则表达式&…

【Docker项目实战】使用Docker部署HumHub社交网络平台

【Docker项目实战】使用Docker部署HumHub社交网络平台 一、HumHub介绍1.1 HumHub简介1.2 HumHub特点1.3 主要使用场景二、本次实践规划2.1 本地环境规划2.2 本次实践介绍三、本地环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本四、下载HumHub镜…

Swin-Transformer

网络整体架构&#xff1a; Swin-transformer与vision transformer对比&#xff1a; Swin-Transformer构建的feature map具有层次性&#xff0c;类似于卷积神经网络&#xff0c;随着特征层的不断加深&#xff0c;feature map的高和宽是不断减小的&#xff1b;层次性使Swin-Tran…

什么是优秀的单元测试?

阅读本文之前&#xff0c;请投票支持这款 全新设计的脚手架 &#xff0c;让 Java 再次伟大&#xff01; 单元测试的质量意义 合理编写单元测试&#xff0c;可使团队工程师告别牛仔式编程&#xff0c;产出易维护的高质量代码。随着单元测试覆盖率的上升&#xff0c;项目会更加…

学习笔记——交换——STP(生成树)桥协议数据单元(BPDU)

四、桥协议数据单元(BPDU) 1、BPDU基本概念 桥协议数据单元(Bridege Protocol Data Unit,BPDU)BPDU是STP的协议报文&#xff0c;直接封装在二层协议&#xff0c;是传输载体。是STP能够正常工作的根本。 BPDU主要由 4 部分组成&#xff1a; (1)根桥ID (2)发送者到根桥的开…