Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【Netty4.x教程】Netty 开启SSL支持 #17

Open
TFdream opened this issue May 30, 2020 · 0 comments
Open

【Netty4.x教程】Netty 开启SSL支持 #17

TFdream opened this issue May 30, 2020 · 0 comments

Comments

@TFdream
Copy link
Owner

TFdream commented May 30, 2020

生成自签证书

1、生成自签证书

可以参考这篇 使用keytool工具生成证书

关于keytool的官方说明:https://docs.oracle.com/javase/6/docs/technotes/tools/solaris/keytool.html

2、客户端导入证书

对于自签证书 需要在客户端进行导入,导入证书命令如下:

keytool -import -trustcacerts -alias netty -keystore $JAVA_HOME/jre/lib/security/cacerts -file nginx.crt -storepass changeit 

例如:

RickydeMBP:netty-in-action apple$ sudo keytool -import -trustcacerts -alias netty -keystore /Library/Java/JavaVirtualMachines/jdk1.8.0_171.jdk/Contents/Home/jre/lib/security/cacerts -file /var/folders/_y/q3j1y2fn6996rzfd8_50xzjm0000gn/T/keyutil_example.com_2847488297227795850.crt -storepass changeit

会提示 是否信任此证书? 输入 y 即可。控制台输出如下:

所有者: CN=example.com
发布者: CN=example.com
序列号: 9ac1b92fa3e2812
有效期为 Sat Jun 01 10:58:41 CST 2019 至 Sat Jan 01 07:59:59 CST 10000
证书指纹:
	 MD5:  92:5C:7A:F6:56:F5:04:6C:AF:D3:AD:1D:09:B0:3E:E1
	 SHA1: 59:29:5E:19:BE:B7:9D:4F:FB:96:0B:5E:A8:F8:7F:1C:19:0F:BB:D3
	 SHA256: AC:7E:DB:8F:84:16:A5:49:CE:C2:BB:CD:A2:E9:C5:1B:F1:38:C6:9D:FA:51:E6:82:34:FB:66:52:35:9C:53:16
签名算法名称: SHA256withRSA
主体公共密钥算法: 2048 位 RSA 密钥
版本: 3
是否信任此证书? [否]:  y
证书已添加到密钥库中

删除:

keytool -delete -alias netty -keystore $JAVA_HOME/jre/lib/security/cacerts  -storepass changeit 

Netty开启SSL

Netty中提供了io.netty.handler.ssl.SslHandler类,使用起来非常便捷。

本文中使用的Netty版本为 4.1.42.Final,不同版本可能略有不同。

Server端

代码如下:

    public void run() throws Exception {

        EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        UserAuthHandler userAuthHandler = new UserAuthHandler();

        //SSL
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        System.out.println(ssc.certificate());
        System.out.println(ssc.privateKey());

        SslContext sslContext = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
                .build();

        try {
            ServerBootstrap b = new ServerBootstrap(); // (2)
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class) // (3)
                    .handler(new LoggingHandler(LogLevel.INFO)) //增加LOG
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new ChannelInitializer<NioSocketChannel>() { // (4)
                        @Override
                        public void initChannel(NioSocketChannel ch) throws Exception {
                            //pipeline
                            ChannelPipeline pipeline = ch.pipeline();

                            //增加LOG
                            pipeline.addLast("loggingHandler", new LoggingHandler(LogLevel.INFO));

                            //空闲检测
                            pipeline.addLast("idleCheckHandler", new ServerIdleCheckHandler());

                            //SSL
                            SslHandler sslHandler = sslContext.newHandler(ch.alloc());
                            pipeline.addLast("sslHandler", sslHandler);

                            //注意:顺序不能错
                            //handler的顺序:读保证自上而下,写保证自下而上就行了,读与写之间其实顺序无所谓,但是一般为了好看对称,我们是一组一组写。
                            pipeline.addLast("orderFrameDecoder", new OrderFrameDecoder());
                            pipeline.addLast("orderFrameEncoder", new OrderFrameEncoder());

                            pipeline.addLast("orderProtocolEncoder", new OrderProtocolEncoder());
                            pipeline.addLast("orderProtocolDecoder", new OrderProtocolDecoder());

                            //用户身份鉴权
                            pipeline.addLast("userAuthHandler", userAuthHandler);

                            pipeline.addLast("orderProcessHandler", new OrderServerProcessHandler());
                        }
                    });

            // Bind and start to accept incoming connections.
            ChannelFuture f = b.bind(port).sync(); // (7)
            LOG.info("点餐系统-服务端, port:{} 启动完成", port);

            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

Client端

代码如下:

    public void run() throws Exception {
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        //SSL
        SslContext sslContext = SslContextBuilder.forClient()
                .build();
        try {
            Bootstrap b = new Bootstrap(); // (1)
            b.group(workerGroup); // (2)
            b.channel(NioSocketChannel.class); // (3)
            b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
            b.handler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    //pipeline
                    ChannelPipeline pipeline = ch.pipeline();

                    //增加LOG
                    pipeline.addLast("loggingHandler", new LoggingHandler(LogLevel.INFO));

                    //SSL
                    SslHandler sslHandler = sslContext.newHandler(ch.alloc());
                    pipeline.addLast("sslHandler", sslHandler);

                    //空闲检测
                    pipeline.addLast("idleStateHandler", new IdleStateHandler(0, 15, 0, TimeUnit.SECONDS));

                    //注意:顺序不能错
                    //handler的顺序:读保证自上而下,写保证自下而上就行了,读与写之间其实顺序无所谓,但是一般为了好看对称,我们是一组一组写。
                    pipeline.addLast("orderFrameDecoder", new OrderFrameDecoder());
                    pipeline.addLast("orderFrameEncoder", new OrderFrameEncoder());

                    pipeline.addLast("orderProtocolEncoder", new OrderProtocolEncoder());
                    pipeline.addLast("orderProtocolDecoder", new OrderProtocolDecoder());

                    //心跳检测
                    pipeline.addLast("keepLiveHandler", new ClientKeepLiveHandler());

                    //处理响应结果
                    pipeline.addLast("orderClientHandler", new OrderClientHandler());

                }
            });

            // Start the client.
            ChannelFuture f = b.connect(host, port).sync(); // (5)
            LOG.info("点餐系统-客户端, 连接服务器:{}:{}", host, port);

            //身份鉴权
            Command authCommand = new AuthCommand("admin", "admin");
            RpcRequest authRequest = new RpcRequest(IdUtils.nextRequestId(), authCommand);
            //发送
            f.channel().writeAndFlush(authRequest);

            //1.发送点餐请求
            Long requestId = IdUtils.nextRequestId();
            Command command = new OrderCommand(IdUtils.nextSeatId(), Arrays.asList("鱼香肉丝"));
            RpcRequest request = new RpcRequest(requestId, command);

            //2.写入
            f.channel().writeAndFlush(request);
            LOG.info("点餐系统-客户端, 向服务器:{}:{} 发送点餐请求requestId:{}, 请求报文:{}",
                    host, port, requestId, JsonUtils.toJson(request));

            //3.等待响应结果
            CommandResultFuture future = new CommandResultFuture();
            RequestPendingCenter.INSTANCE.add(requestId, future);

            //3.1 获取结果
            CommandResult result = future.get();
            LOG.info("点餐系统-客户端, 收到服务器:{}:{} 请求requestId:{} 响应结果:{}",
                    host, port, requestId, JsonUtils.toJson(result));

            // Wait until the connection is closed.
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }

相关资料

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant