Netty使用SslHandler实现加密通信-单向认证篇

引入依赖

xml 复制代码
<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-all</artifactId>
  <version>4.1.100.Final</version>
</dependency>

生成keystore.jks文件

shell 复制代码
keytool -genkeypair -alias your_alias -keyalg RSA -keystore keystore.jks -keysize 2048

Server端

java 复制代码
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.CharsetUtil;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;

public class NettySslServer {

    private static final int PORT = 8888;

    public static void main(String[] args) throws Exception {
        // 加载SSL证书
        String keyStorePath = "/home/admin/keystore.jks";
        String keyStorePassword = "happya";

        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(new FileInputStream(keyStorePath), keyStorePassword.toCharArray());
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), null, null);

        // 创建EventLoopGroup
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            // 创建服务器Bootstrap
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 在ChannelPipeline中添加SSL处理器
                            SSLEngine sslEngine = sslContext.createSSLEngine();
                            sslEngine.setUseClientMode(false);
                            pipeline.addLast(new SslHandler(sslEngine));
                            // 添加加密通信处理器
                            pipeline.addLast(new SecureChatServerHandler());
                        }
                    })
                    .childOption(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // 启动服务器
            System.out.println("======Begin to start ssl server======");
            ChannelFuture future = serverBootstrap.bind(PORT).sync();
            System.out.println("======Ssl server started======");
            future.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static class SecureChatServerHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            // 当连接建立时,发送欢迎消息
            System.out.println("Server channel active : " + ctx.channel().toString());
            ctx.channel().writeAndFlush(Unpooled.wrappedBuffer("Welcome to the secure chat server!\n".getBytes(StandardCharsets.UTF_8)));
            ctx.channel().writeAndFlush(Unpooled.wrappedBuffer("Your connection is protected by SSL.\n".getBytes(StandardCharsets.UTF_8)));
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            ByteBuf byteBuf= (ByteBuf) msg;
            System.out.println("Server received message: " + byteBuf.toString(CharsetUtil.UTF_8));
            super.channelRead(ctx, msg);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            // 处理异常
            cause.printStackTrace();
            ctx.close();
        }
    }
}

Client端

java 复制代码
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.ssl.SslHandler;
import io.netty.util.CharsetUtil;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;

public class NettySslClient {

    private static final String HOST = "localhost";
    private static final int PORT = 8888;

    public static void main(String[] args) throws Exception {
        // 加载SSL证书
        String trustStorePath = "/home/admin/keystore.jks";
        String trustStorePassword = "happya";

        // 创建SSL上下文
        SSLContext sslContext = SSLContext.getInstance("TLS");
        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);

        // 创建EventLoopGroup
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            // 创建客户端Bootstrap
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 在ChannelPipeline中添加SSL处理器
                            SSLEngine sslEngine = sslContext.createSSLEngine();
                            sslEngine.setUseClientMode(true);
                            pipeline.addLast(new SslHandler(sslEngine));
                            // 添加加密通信处理器
                            pipeline.addLast(new SecureChatClientHandler());
                        }
                    });

            // 连接服务器
            System.out.println("======Begin to start ssl client======");
            ChannelFuture future = bootstrap.connect(HOST, PORT).sync();
            System.out.println("======Ssl client started======");
            future.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }

    public static class SecureChatClientHandler extends ChannelInboundHandlerAdapter {

        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            // 连接建立时,发送一条消息给服务器
            System.out.println("Client channel active : " + ctx.channel().toString());
            ctx.channel().writeAndFlush(Unpooled.wrappedBuffer("Hello from client!\n".getBytes(StandardCharsets.UTF_8)));
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            ByteBuf byteBuf = (ByteBuf) msg;
            System.out.println("Client received message: \n" + byteBuf.toString(CharsetUtil.UTF_8));
            super.channelRead(ctx, msg);
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            // 处理异常
            cause.printStackTrace();
            ctx.close();
        }
    }
}
相关推荐
beiback2 天前
Springboot + netty + rabbitmq + myBatis
spring boot·mysql·rabbitmq·mybatis·netty·java-rabbitmq
山塘小鱼儿10 天前
Netty+HTML5+Canvas 网络画画板实时在线画画
java·前端·网络·netty·html5
学海无涯,行者无疆19 天前
通用接口开放平台设计与实现——(31)API服务线程安全问题确认与修复
接口·netty·开放平台·接口开放平台·通用接口开放平台
马丁的代码日记1 个月前
Netty中用到了哪些设计模式
java·开发语言·设计模式·netty
wang09071 个月前
netty编程之整合es实现存储以及搜索功能
大数据·elasticsearch·搜索引擎·netty
邂逅岁月1 个月前
【网络原理】Udp 的报文结构,保姆式教学,快速入门
网络·网络协议·tcp/ip·计算机网络·udp·信息与通信·网络通信
huisheng_qaq1 个月前
【netty系列-09】深入理解和解决tcp的粘包拆包
tcp/ip·网络编程·netty·网络通信·粘包拆包·粘包拆包解决方案
大作业管家1 个月前
netty开发模拟qq斗地主
netty·qq斗地主
邂逅岁月1 个月前
【网络原理】从0开始学习计算机网络常识,中学生看了都能学会
网络·网络协议·学习·tcp/ip·计算机网络·操作系统·网络通信
huisheng_qaq1 个月前
【netty系列-08】深入Netty组件底层原理和基本实现
java·netty·context·eventloop·channelhandler·netty原理及实现