netty-websocket服务器配置阿里云SSL证书安全访问配置,亲测有效

本文讲述了作者在Java微服务中遇到的HTTPS访问WebSocket的问题,详细描述了如何在使用Netty时配置SSL证书,包括从阿里云申请免费证书、转换证书格式(PKCS12转PKCS8),以及如何在代码中正确集成这些证书以支持WSS。
摘要由CSDN通过智能技术生成

背景:java 微服务包括https访问和websocket访问,当https接口访问ws请求时报错,因为https能访问wss。

申请阿里云免费证书后,搜索各种教程比如nginx配置方式、netty访问证书等。走了不少弯路,终于走通一种。

关键点:1、因为使用了netty,nginx配置wss的方式没有走通。需要将证书放到netty启动的方式启动才可以。

2、网上教程大多数是pkcs12的证书生成方式。但是netty仅仅支持pkcs8 的版本,所以需要生成pkcs12之后再转pkcs8.

一、阿里云申请免费证书

二、生成pem、key的证书

1、下载类型Nginx的pem证书

2、下载类型Tomcat的pfx

证书,在jdk的路径下cmd命令生成(也可以直接在文件夹里面)server.key文件,输入命令,密码是同时在一起的pfx-password.txt里面

openssl pkcs12 -in *******.pfx -nocerts -nodes -out server.key

3、因为netty仅仅支持pkcs8,所以将server.key 通过OpenSSl 生成pkcs8的版本

安装openssl

windows电脑下载已经编译好的openssl
OpenSSL for Windows

或者

OpenSSL官方下载 - 码客
然后将安装路径加到环境变量中

cmd 命令生成server8.key:

openssl pkcs8 -topk8 -inform PEM -in server.key -outform pem -nocrypt -out server8.key

三、编写代码

仅仅需要增加两个地方:

1、启动的start方法,增加server8.key和pem文件的读取

全局变量

private SslContext sslContext;//netty 配置ssl证书、WSS地址访问。备注:netty 仅仅使用pkcs8的证书,需要使用openssl转

将证书放到main/resources下面,则用ClassPathResource读取

//ssl证书配置--放到项目中
ClassPathResource pem = new ClassPathResource("service.sv3d.cn.pem");
ClassPathResource key = new ClassPathResource("server8.key");
this.sslContext = SslContextBuilder.forServer(pem.getInputStream(),key.getInputStream()).build();

将证书放到外面,方便后期更换,毕竟免费的证书是一年一申请的,用InputStream读取

//ssl证书配置--放到外部
InputStream pemInputStream = new FileInputStream("E:\\zhengshu\\9760642_service.sv3d.cn_nginx\\9760642_service.sv3d.cn.pem"); /// 证书存放地址
InputStream keyInputStream = new FileInputStream("E:\\zhengshu\\9760642_service.sv3d.cn_tomcat\\server8.key"); /// 证书存放地址
this.sslContext = SslContextBuilder.forServer(pemInputStream,keyInputStream).build();

2、initChannel 方法添加ssl的验证

ch.pipeline().addLast(sslContext.newHandler(ch.alloc()));

3、全部代码,仅看修改部分就行,大同小异。

    /**
     * 启动
     * @throws InterruptedException
     */
    private void start() throws InterruptedException {
    	try {
			port = Integer.parseInt(optionService.getByKey(OptionKey.SocketPort.getKey()).getValue());

			String wsFlag = nacosConfigProp.getWsFlag();
			 //ssl证书配置--放到外部
                //InputStream pemInputStream = new FileInputStream("E:\\zhengshu\\9760642_service.sv3d.cn_nginx\\9760642_service.sv3d.cn.pem"); /// 证书存放地址
                //InputStream keyInputStream = new FileInputStream("E:\\zhengshu\\9760642_service.sv3d.cn_tomcat\\server8.key"); /// 证书存放地址
                //this.sslContext = SslContextBuilder.forServer(pemInputStream,keyInputStream).build();
                //ssl证书配置--放到项目中
                ClassPathResource pem = new ClassPathResource("service.sv3d.cn.pem");
                ClassPathResource key = new ClassPathResource("server8.key");
                this.sslContext = SslContextBuilder.forServer(pem.getInputStream(),key.getInputStream()).build();

		} catch (Exception e) {
			e.printStackTrace();
		}
        //数据量上来时设置线程池
        /*bossGroup = new NioEventLoopGroup(2,new DefaultThreadFactory("server1",true));
        workGroup = new NioEventLoopGroup(4,new DefaultThreadFactory("server2",true));*/
    	// 获取Reactor线程池
    	bossGroup = new NioEventLoopGroup();
        workGroup = new NioEventLoopGroup();
        // 服务端启动辅助类,用于设置TCP相关参数
        ServerBootstrap bootstrap = new ServerBootstrap();
        // bossGroup辅助客户端的tcp连接请求, workGroup负责与客户端之前的读写操作,设置为主从线程模型
        bootstrap.group(bossGroup,workGroup);
        //禁用nagle算法
        bootstrap.childOption(ChannelOption.TCP_NODELAY, true); 
       
        //bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024*1024, 40*1024*1024)); 
        
        //当设置为true的时候,TCP会实现监控连接是否有效,当连接处于空闲状态的时候,超过了2个小时,
        //本地的TCP实现会发送一个数据包给远程的 socket,如果远程没有发回响应,TCP会持续尝试11分钟,
        //知道响应为止,如果在12分钟的时候还没响应,TCP尝试关闭socket连接。
        bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); 
        // 设置NIO类型的channel,设置服务端NIO通信类型
        bootstrap.channel(NioServerSocketChannel.class);
        // 设置监听端口
        bootstrap.localAddress(new InetSocketAddress(port));
        // 连接到达时会创建一个通道,设置ChannelPipeline,也就是业务职责链,由处理的Handler串联而成,由从线程池处理
        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
        	// 添加处理的Handler,通常包括消息编解码、业务处理,也可以是日志、权限、过滤等
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
                // 流水线管理通道中的处理程序(Handler),用来处理业务
                
            	  //=============================增加心跳支持============================

                //添加ssl 访问
                ch.pipeline().addLast(sslContext.newHandler(ch.alloc()));

            	// webSocket协议本身是基于http协议的,所以这边也要使用http编解码器
                ch.pipeline().addLast(new HttpServerCodec());
                ch.pipeline().addLast(new ObjectEncoder());
                //ch.pipeline().addLast(myMessageDncoder);
                //ch.pipeline().addLast(myMessageEncoder);
                // 以块的方式来写的处理器,分块向客户端写数据,防止发送大文件时导致内存溢出,channel.write(new ChunkedFile(new File("...")))
                ch.pipeline().addLast(new ChunkedWriteHandler());
                //ch.pipeline().addLast(new MyServerChunkHandler());
		        /*
		        说明:
		        1、http数据在传输过程中是分段的,HttpObjectAggregator可以将多个段聚合
		        2、这就是为什么,当浏览器发送大量数据时,就会发送多次http请求
		         */
                //需要放到HttpServerCodec后面
		        ch.pipeline().addLast(new HttpObjectAggregator(65535));//10kb?
		        //websocket数据压缩扩展,当添加这个的时候,WebSocketServerProtocolHandler第三个参数需要设置成true
		        ch.pipeline().addLast(new WebSocketServerCompressionHandler());
		        /*
		        说明:
		        1、对应webSocket,它的数据是以帧(frame)的形式传递
		        2、浏览器请求时 ws://localhost:58080/xxx 表示请求的uri
		        3、核心功能是将http协议升级为ws协议,保持长连接
		        */
		       
		        
		        //对客户端,如果在60秒内没有向服务端发送心跳,就主动断开
		        //三个参数分别为读/写/读写的空闲,我们只针对读写空闲检测
		        //ch.pipeline().addLast(new IdleStateHandler(10,11,12,TimeUnit.SECONDS));
		        //ch.pipeline().addLast(heartBeatHandler);
		        
		        // 自定义的handler,处理业务逻辑
		        //ch.pipeline().addLast(webSocketHandler);
		        //ch.pipeline().addLast(userLoginRespHandler);
		        ch.pipeline().addLast(textWebSocketHandler);
		        ch.pipeline().addLast(binaryWebSocketFrameHandler);
		        // 服务器端向外暴露的 web socket 端点,当客户端传递比较大的对象时,maxFrameSize参数的值需要调大
		        ch.pipeline().addLast(new WebSocketServerProtocolHandler(webSocketPath, webSocketProtocol, true, 10485760));//10mb?

            }
        });
        // 配置完成,开始绑定server,通过调用sync同步方法阻塞直到绑定成功
        ChannelFuture channelFuture = bootstrap.bind().sync();
        log.info("Server started and listen on:{}",channelFuture.channel().localAddress());
        // 对关闭通道进行监听
        channelFuture.channel().closeFuture().sync();
    }

四、验证是否通,采用Postman或者自己写界面都行。

配置完了,发现ws不能使用了,还在研究,各位大神有办法,可以留言,互相学习。下面是下载的别人的案例,然后改了下我的案例,所以里面有两个server,可以做下参考。

WebsocketServer1是我的方案,证书按照文章里面的证书下载生成,启动WebsocketServer1的main方法,用postman访问是可以的,但是用他绑定的html不行,但是在我的项目里面是可以的。

java访问案例

另一种方式是WebsocketServer生成key然后配置密码的方式,我尝试过,生成的密码每次都是不匹配,所以放弃了。

接下来我将给各位同学划分一张学习计划表!

学习计划

那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:

阶段一:初级网络安全工程师

接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。

综合薪资区间6k~15k

1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?

阶段二:中级or高级网络安全工程师(看自己能力)

综合薪资区间15k~30k

7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。

零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;

Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完

用Python编写漏洞的exp,然后写一个简单的网络爬虫

PHP基本语法学习并书写一个简单的博客系统

熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)

了解Bootstrap的布局或者CSS。

阶段三:顶级网络安全工程师

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。

你可以按照以下步骤来配置 SSL 访问 WebSocket: 1. 生成证书和私钥文件,可以使用 OpenSSL 工具。 2. 将证书和私钥文件放在服务器上,并记录其存储路径。 3. 在 Spring Boot 项目的 application.properties 或 application.yml 文件中配置 SSL 相关属性,如下所示: ``` server: port: 443 ssl: enabled: true key-store: /path/to/your/keystore.p12 key-store-password: your_password key-store-type: PKCS12 ``` 其中,`server.port` 指定端口号,这里设置为 443,即 HTTPS 默认端口号;`server.ssl.enabled` 表示启用 SSL;`server.ssl.key-store` 指定证书和私钥文件的存储路径;`server.ssl.key-store-password` 指定证书和私钥文件的密码;`server.ssl.key-store-type` 指定证书和私钥文件的类型,这里设置为 PKCS12。 4. 在 WebSocket 配置类中添加 SSL 相关配置,如下所示: ```java @Configuration @EnableWebSocket public class WebSocketConfig implements WebSocketConfigurer { @Override public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) { registry.addHandler(new MyWebSocketHandler(), "/websocket") .setAllowedOrigins("*") .withSockJS(); } @Bean public ServletServerContainerFactoryBean createWebSocketContainer() { ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean(); container.setMaxTextMessageBufferSize(8192); container.setMaxBinaryMessageBufferSize(8192); container.setMaxSessionIdleTimeout(30000); container.setAsyncSendTimeout(5000); container.setTaskExecutor(new ConcurrentTaskExecutor()); container.setWebSocketTransport(new StandardWebSocketTransport()); container.setSsl(getSslConfiguration()); return container; } private SslConfiguration getSslConfiguration() { SslConfiguration ssl = new SslConfiguration(); ssl.setKeyStore("/path/to/your/keystore.p12"); ssl.setKeyStorePassword("your_password"); ssl.setKeyStoreType("PKCS12"); return ssl; } } ``` 其中,`createWebSocketContainer` 方法用于创建 WebSocket 容器,可以通过其设置最大文本消息缓冲大小、最大二进制消息缓冲大小、最大会话空闲时间、异步发送超时时间、任务执行器、WebSocket 传输协议以及 SSL 配置。 `getSslConfiguration` 方法用于获取 SSL 配置,与 application.properties 或 application.yml 中的配置相同。 至此,你已经完成了 SSL 访问 WebSocket配置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值