基于Netty实现安全认证的WebSocket(wss)服务端

1.Netty服务端

服务端代码参考【基于Netty实现WebSocket服务端-CSDN博客】中的两种方式都可以;这里用的是第一种简单方式。

新增如下逻辑:添加SSLHandler

SSLContext sslContext = SslUtil.createSSLContext("JKS","D:\\workSpace\\daydayup\\cert\\wss2\\mystore.jks", "1234567");// SSLEngine 此类允许使用ssl安全套接层协议进行安全通信SSLEngine engine = sslContext.createSSLEngine();engine.setUseClientMode(false);pipeline.addLast(new SslHandler(engine)); // 设置SSL

SslUtil的代码:

import org.springframework.core.io.DefaultResourceLoader;import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;public class SslUtil {public static SSLContext createSSLContext(String type, String path, String sslPassword) throws Exception {DefaultResourceLoader resourceLoader = new DefaultResourceLoader();InputStream inputStream = new FileInputStream(path);char[] passArray = sslPassword.toCharArray();SSLContext sslContext = SSLContext.getInstance("SSLv3"); // 这里TLS或者SSLv3都可以KeyStore ks = KeyStore.getInstance("JKS");// 加载keytool 生成的文件ks.load(inputStream, passArray);KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());kmf.init(ks, passArray);sslContext.init(kmf.getKeyManagers(), null, null);inputStream.close();return sslContext;}
}

完整的服务端代码如下:

MyTextWebSocketFrameHandler的代码和 【基于Netty实现WebSocket服务端-CSDN博客】中的完全一样。

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;/**** 实现长链接 客户端与服务端;*/
public class SimpleWssChatServer {public static void main(String[] args) throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workGroup = new NioEventLoopGroup();try {ServerBootstrap serverBootstrap = new ServerBootstrap();serverBootstrap.group(bossGroup, workGroup).channel(NioServerSocketChannel.class).// 在 bossGroup 增加一个日志处理器handler(new LoggingHandler(LogLevel.INFO)).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel socketChannel) throws Exception {ChannelPipeline pipeline = socketChannel.pipeline();SSLContext sslContext = SslUtil.createSSLContext("JKS","D:\\workSpace\\daydayup\\cert\\wss2\\mystore.jks", "1234567");// SSLEngine 此类允许使用ssl安全套接层协议进行安全通信SSLEngine engine = sslContext.createSSLEngine();engine.setUseClientMode(false);pipeline.addLast(new SslHandler(engine)); // 设置SSL// 基于http协议的长连接 需要使用http协议的解码 编码器pipeline.addLast(new HttpServerCodec());// 以块的方式处理pipeline.addLast(new ChunkedWriteHandler());/*** http数据传输过程中是分段, HttpObjectAggregator 将多个段聚合起来* 当浏览器发起大量数据的时候,会发起多次http请求*/pipeline.addLast(new HttpObjectAggregator(8192));/*** 对于websocket是以frame的形式传递* WebSocketFrame*  浏览器 ws://localhost:7000/ 不在是http协议*  WebSocketServerProtocolHandler 将http协议升级为ws协议 即保持长链接*/pipeline.addLast(new WebSocketServerProtocolHandler("/helloWs"));// 自定义handler专门处理浏览器请求pipeline.addLast(new MyTextWebSocketFrameHandler());}});ChannelFuture channelFuture = serverBootstrap.bind(7070).sync();channelFuture.channel().closeFuture().sync();} finally {bossGroup.shutdownGracefully();workGroup.shutdownGracefully();}}
}

2.使用jdk工具keytool生成证书

证书处理步骤如下,缺一不可

#2.1生成秘钥对
keytool -genkey -alias server2 -keyalg RSA -validity 365 -keystore D:\workSpace\daydayup\cert\wss2\mystore.jks -storepass 1234567

#2.2导入证书
keytool  -alias server2 -exportcert  -keystore D:\workSpace\daydayup\cert\wss2\mystore.jks -file D:\workSpace\daydayup\cert\wss2\mystore.cer -storepass 1234567
#2.3信任证书

双机上面生成的证书文件mystore.cer,

可以看到证书此时不受信任,点击【安装证书】

选择存储位置为【本地计算机】后,

 选择证书存储为【受信任的根证书颁发机构】,完成即可。

再次双击原证书,可以看到证书已经受信任了

3.使用JavaScript客户端进行测试:

JavaScript客户端代码,也是和 【基于Netty实现WebSocket服务端-CSDN博客】中基本一样,只是把服务端地址的协议头修改为wss。

socket = new WebSocket("wss://localhost:7070/helloWs");

启动服务端,然后启动客户端,连接和接发数据都正常。

windows下的wss访问到此就可以拉。

4.下面列一些在开发过程中遇到的问题:

4.1生成mystore.jks后,不导入证书,直接启动服务端使用;

或者导入证书后不手动信任,客户端进行连接时候,会报错

io.netty.handler.codec.DecoderException: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknownat io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:459)at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1359)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:935)at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:138)at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:645)at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:545)at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:499)at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknownat java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:365)at java.base/sun.security.ssl.Alert$AlertConsumer.consume(Alert.java:293)at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:204)at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:172)at java.base/sun.security.ssl.SSLEngineImpl.decode(SSLEngineImpl.java:736)at java.base/sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:691)at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:506)at java.base/sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:482)at java.base/javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:679)at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:292)at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1247)at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1158)at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1193)at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)... 16 more

4.2 客户端连接服务端的地中,协议头还是ws

异常发生:io.netty.handler.ssl.NotSslRecordException: not an SSL/TLS record: 

参考:netty整合websocket支持自签证书出现netty websocket ssl Received fatal alert: certificate_unknown_alert certificate unknown-CSDN博客

netty做服务端支持ssl协议实现websocket的wss协议(客户端为浏览器)_netty websocket ssl-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842439.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Web(数字媒体)期末作业

一.前言 1.本资源为类似于打飞机的网页游戏 2.链接如下&#xff1a;【免费】前端web或者数字媒体的期末作业&#xff08;类似于打飞机的2D网页小游戏&#xff09;资源-CSDN文库 二.介绍文档

SAP HCM 标准程序如何定位内表赋值 ABAP DEBUG SCRIPT

Complacency is the enemy of study 学习的敌人是自己的满足。 标准内表定位代码位置!!! 不知道大家有没有尝试体会过debug标准程序,debug过程中发现SAP标准的内表不知道什么时候赋值,或者类的静态属性什么时候改变的,本文通过ABAP DEBUG SCRIPT的方式快速定位内表赋值或者类…

VM中Ubuntu16.04的下载以及ROS—kinetic的版本下载

一、Ubuntu镜像地址 转载备份一下&#xff1b; 官方下载地址&#xff08;不推荐&#xff09; https://www.ubuntu.com/downloadhttps://www.ubuntu.com/download 中科大源 Index of /ubuntu-releases/16.04/http://mirrors.ustc.edu.cn/ubuntu-releases/16.04/ 阿里云开…

基于51单片机的电压表-数码管显示

一.硬件方案 本设计基于STC89C52单片机的一种电压测量电路&#xff0c;该电路采用ADC0832A/D转换芯片,实现数字电压表的硬件电路与软件设计。该系统的数字电压表电路简单, 可以测量0&#xff5e;9V的电压值,并在四位LED数码管上显示电压值。 二.设计功能 &#xff08;1&…

工业网关设备:HiWoo Box网关

在数字化、智能化的工业浪潮中&#xff0c;工业网关以其卓越的性能和广泛的应用场景&#xff0c;成为了工业互联的核心驱动力。作为一款高效、稳定、智能的工业网关设备&#xff0c;HiWoo Box网关不仅实现了工业现场设备与网络的高效连接&#xff0c;更为企业提供了智能化的数据…

使用 Spring 事件监听机制实现跨模块调用

之前一个项目&#xff0c;有两个模块&#xff0c;A 模块需要依赖 B 模块&#xff0c;但现在 B 模块有地方需要调用 A 模块的方法&#xff0c;如果直接依赖&#xff0c;又会产生循环依赖问题。最终选择使用 spring 的事件监听来解决该问题。 思路就是&#xff0c;B 模块去发布事…

JAVA ---JAVA运算符详解

运算符:对操作数进行操作的符号 运算符分为:算术运算符 关系运算符 逻辑运算符 位运算符 移位运算符 条件运算符 1.算术运算符 基本四则运算符 增量运算符 自增自减运算符 1.1 基本四则运算符&#xff1a;加减乘除模( - * / %) int a 20; int b 10; System.out.println(a…

【linux】linux中免交互命令expect原理与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全…

智能客服新突破:大型模型训练助力提升客户服务体验

项目场景&#xff1a;训练大模型智能客服 智能客服新方法在金融服务领域的科技前沿应用 ** 一、 引言 随着科技的飞速发展&#xff0c;智能客服作为金融服务领域的一大创新点&#xff0c;正在逐渐改变传统的客户服务模式。特别是在自然语言处理&#xff08;NLP&#xff09;等…

【C++】多态:编程中的“一人千面”艺术

目录 一、多态的概念二、多态的定义及实现1.多态的构成条件2.虚函数的重写2.1 什么是虚函数&#xff1f;2.2 虚函数的重写是什么&#xff1f;2.3 虚函数重写的两个例外2.4 C11 override 和 final2.5 重载、覆盖(重写)、隐藏(重定义)的对比 三、抽象类3.1 概念3.2 接口继承和实现…

重学java 47.集合 ② 迭代器

金榜题名&#xff0c;前程似锦 —— 24.5.27 一、迭代器的介绍和使用 1.概述 Iterator接口 2.主要作用 遍历集合 3.获取 Collection中的方法&#xff1a; Iterator<E> iterator() 4.方法 boolean hasNext() —> 判断集合中有没有下一个元素 E.next() —> 获取下一个…

《QT实用小工具·六十六》基于QT开发的界面收缩栏

1、概述 源码放在文章末尾 该项目实现了一个界面收缩栏的效果&#xff0c;该收缩栏包含如下功能&#xff1a; 1、可以在收缩栏中添加若干个界面 2、鼠标点击收缩栏可以展开或收起界面 3、鼠标拖动收缩栏可以和其他界面互换位置 项目demo演示如下所示&#xff1a; 使用方式&…

iptables 规则参数

本文只是记录常用的命令行规则&#xff0c;如果想了解和学习 iptables&#xff0c;请移步《IPtables》 每一条匹配规则都可以使用 ! 进行取反。如 ! --dport 22 表示所有目标端口不为 22 的请求 下表为链和表的对应关系 ChainTablePREROUTINGraw表&#xff0c;mangle表&…

小甲零基础入门学习Python(全96集)

介绍 本课程旨在为学者提供关于Python 3.x版本的基础教学&#xff0c;确保学员能够熟练掌握其语法结构。通过整合讲师的实际工作经验&#xff0c;课程内容不仅覆盖了Python的应用技巧&#xff0c;还深入讨论了相关的数据结构知识。为了增强学习效果&#xff0c;我们精心准备了…

Unable to find a node that satisfies the following conditions [port xxxx]

Unable to find a node that satisfies the following conditions [port xxxx] 原因&#xff1a;当容器使用端口映射(docker run -p xxxx:xxxx或 compose模板中的 ports)之后 系统会在宿主机上创建一个port&#xff0c;通过NAT来访问容器的指定port。如果宿主机上的端口被容器或…

版本控制(Version Control)(GIT )

版本控制系统的基本概念 版本库&#xff08;Repository&#xff09;&#xff1a;存储项目版本的本地或远程存储库。工作副本&#xff08;Working Copy&#xff09;&#xff1a;可编辑的项目本地副本。文件&#xff08;File&#xff09;&#xff1a;项目中的单个文件。版本&…

jenkins 用户权限(Manage-Roles)

本次需求将DEV环境和SIT环境分开,SIT用户登录上来只能看他的SIT项目和视图 安装roles插件 进入 manage role 项目授权 用户 正则匹配你需要的项目 dev .*-dev*或者.*-dev$ sit .*-sit最后细分assign role 测试使用sit账号登录 ,视图和项目都是SIT账号的

爬虫视图展示之 Power BI

实现方式 读取数据的实现 selenium 库 requests 库 存储媒介 MysqlElasticSearch 图表展示 GrafanaPower BI 是什么&#xff1f; Power BI 简单且快速&#xff0c;能够从 Excel 电子表格或本地数据库创建快速见解。 同时 Power BI 也可进行丰富的建模和实时分析&#xff…

移动云:开发者手中的未来钥匙

《移动云&#xff1a;开发者手中的未来钥匙》 引言一、无缝集成&#xff0c;加速开发进程二、数据智能&#xff0c;洞悉用户心声三、安全合规&#xff0c;护航创新之旅四、成本优化&#xff0c;助力轻装前行总结 引言 在科技日新月异的今天&#xff0c;移动云已成为推动行业变革…

kube-apiserver内存占用过多 go tool pprof 入门

目录 环境问题排查1、kube-apiserver %CPU 146 正常&#xff0c;%MEM 高达70&#xff0c;&#xff0c;load average 400&#xff0c;出现kswapd0进程。2、k describe node 看到 SystemOOM3、是否大量连接导致&#xff1f;4、通过prom查看指标5、访问K8s API6、pprof 火焰图 解决…