Netty使用SslHandler实现加密通信

“不积跬步,无以至千里。”

说明

Netty使用SslHandler实现加密通信,认证方式为双向认证,单向认证忽略,话不多说,直接上代码

引入依赖

<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-all</artifactId>
  <version>4.1.100.Final</version>
</dependency>

生成keystore.jks文件

keytool -genkeypair -alias your_alias -keyalg RSA -keystore keystore.jks -keysize 2048

Server端

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.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.util.CharsetUtil;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.InputStream;
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 serverKeyStorePath = "/home/admin/server/keystore.jks";
        String clientKeyStorePath = "/home/admin/client/keystore.jks";
        String serverKeyStorePassword = "happya";
        String clientKeyStorePassword = "happya";

        // 创建SslContext
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (InputStream keyStoreInputStream = new FileInputStream(serverKeyStorePath)) {
            keyStore.load(keyStoreInputStream, serverKeyStorePassword.toCharArray());
        }

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, serverKeyStorePassword.toCharArray());

        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (InputStream trustStoreInputStream = new FileInputStream(clientKeyStorePath)) {
            trustStore.load(trustStoreInputStream, clientKeyStorePassword.toCharArray());
        }

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        SslContext sslContext = SslContextBuilder.forServer(keyManagerFactory)
                    .trustManager(trustManagerFactory)
                    .sslProvider(SslProvider.OPENSSL)
                    .build();
        // 创建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中添加SslHandler
                            pipeline.addLast(sslContext.newHandler(ch.alloc()));
                            // 添加加密通信处理器
                            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端

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.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslProvider;
import io.netty.util.CharsetUtil;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.InputStream;
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 serverKeyStorePath = "/home/admin/server/keystore.jks";
        String clientKeyStorePath = "/home/admin/client/keystore.jks";
        String serverKeyStorePassword = "happya";
        String clientKeyStorePassword = "happya";

        // 创建SslContext
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (InputStream keyStoreInputStream = new FileInputStream(clientKeyStorePath)) {
            keyStore.load(keyStoreInputStream, clientKeyStorePassword.toCharArray());
        }

        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, clientKeyStorePassword.toCharArray());

        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (InputStream trustStoreInputStream = new FileInputStream(serverKeyStorePath)) {
            trustStore.load(trustStoreInputStream, serverKeyStorePassword.toCharArray());
        }

        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // 创建EventLoopGroup
        EventLoopGroup group = new NioEventLoopGroup();
		SslContext sslContext = SslContextBuilder.forClient()
                    .keyManager(keyManagerFactory)
                    .trustManager(trustManagerFactory)
                    .sslProvider(SslProvider.OPENSSL)
                    .build();
        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中添加SslHandler
                            pipeline.addLast(sslContext.newHandler(ch.alloc());
                            // 添加加密通信处理器
                            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();
        }
    }
}

测试结果

server

======Begin to start ssl server======
======Ssl server started======
Server channel active : [id: 0x6cbfa6c6, L:/127.0.0.1:8888 - R:/127.0.0.1:58440]
Server received message: Hello from client!

client

======Begin to start ssl client======
======Ssl client started======
Client channel active : [id: 0x9a642804, L:/127.0.0.1:58440 - R:localhost/127.0.0.1:8888]
Client received message: 
Welcome to the secure chat server!
Your connection is protected by SSL.
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些基本的思路来实现这个问题。 首先,您需要在Spring Boot项目中添加netty依赖。可以使用以下Maven依赖: ```xml <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.63.Final</version> </dependency> ``` 接下来,您可以创建一个UDP服务器和客户端,以实现通信。以下是一个简单的示例: ```java @Component public class UDPServer { private static final int PORT = 8888; @PostConstruct public void start() { NioEventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap() .group(group) .channel(NioDatagramChannel.class) .handler(new ChannelInitializer<DatagramChannel>() { @Override protected void initChannel(DatagramChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new UDPSeverHandler()); } }); bootstrap.bind(PORT).sync().channel().closeFuture().await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } } ``` ```java @Component public class UDPClient { private static final String HOST = "localhost"; private static final int PORT = 8888; private Bootstrap bootstrap; @PostConstruct public void start() { NioEventLoopGroup group = new NioEventLoopGroup(); try { bootstrap = new Bootstrap() .group(group) .channel(NioDatagramChannel.class) .handler(new ChannelInitializer<DatagramChannel>() { @Override protected void initChannel(DatagramChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new UDPClientHandler()); } }); Channel channel = bootstrap.bind(0).sync().channel(); channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8), new InetSocketAddress(HOST, PORT))).sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { group.shutdownGracefully(); } } } ``` 在这个示例中,我们创建了一个UDP服务器和客户端,服务器监听8888端口,客户端向服务器发送"Hello World"的消息。 您还需要实现UDPSeverHandler和UDPClientHandler来处理服务器和客户端的消息。以下是一个简单的示例: ```java public class UDPSeverHandler extends SimpleChannelInboundHandler<DatagramPacket> { @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception { ByteBuf buf = msg.content(); String message = buf.toString(CharsetUtil.UTF_8); System.out.println("Server receive message: " + message); } } ``` ```java public class UDPClientHandler extends SimpleChannelInboundHandler<DatagramPacket> { @Override protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception { ByteBuf buf = msg.content(); String message = buf.toString(CharsetUtil.UTF_8); System.out.println("Client receive message: " + message); } } ``` 这只是一个非常基本的示例,您可以根据需要进行更改和扩展。例如,您可以添加加密/解密,序列化/反序列化等功能来实现更复杂的应用程序。 希望这可以帮助您实现Spring Boot集成netty,并实现UDP的通信

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值